diff --git a/.github/config.json b/.github/config.json index 77bafb729ad7..40f891bdb018 100644 --- a/.github/config.json +++ b/.github/config.json @@ -1 +1 @@ -{"runners":[{"versioning":{"source":"milestones","type":"SemVer"},"prereleaseName":"alpha","issue":{"labels":{"Widgets Product":{"conditions":[{"label":"Button Widget","type":"hasLabel","value":true},{"label":"Chart 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":"New Widget","type":"hasLabel","value":true},{"label":"Switch widget","type":"hasLabel","value":true},{"label":"Audio Widget","type":"hasLabel","value":true},{"label":"Icon Button 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":"View Mode","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":"Button Group widget","type":"hasLabel","value":true},{"label":"Progress bar widget","type":"hasLabel","value":true},{"label":"Audio Recorder Widget","type":"hasLabel","value":true},{"label":"Camera Widget","type":"hasLabel","value":true},{"label":"Table Widget V2","type":"hasLabel","value":true},{"label":"Map Chart Widget","type":"hasLabel","value":true},{"label":"Code Scanner Widget","type":"hasLabel","value":true},{"label":"Widget keyboard accessibility","type":"hasLabel","value":true},{"label":"List Widget V2","type":"hasLabel","value":true},{"label":"Slider Widget","type":"hasLabel","value":true},{"label":"One-click Binding","type":"hasLabel","value":true},{"label":"Old widget version","type":"hasLabel","value":true},{"label":"Widget Discoverability","type":"hasLabel","value":true},{"label":"Switch Group Widget","type":"hasLabel","value":true},{"label":"Checkbox Group widget","type":"hasLabel","value":true},{"label":"Checkbox Widget","type":"hasLabel","value":true},{"label":"Table Inline Edit","type":"hasLabel","value":true},{"label":"Custom Widgets","type":"hasLabel","value":true}],"requires":1},"Javascript Product":{"conditions":[{"label":"JS Linting & Errors","type":"hasLabel","value":true},{"label":"Autocomplete","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 Usability","type":"hasLabel","value":true},{"label":"Framework Functions","type":"hasLabel","value":true},{"label":"JS Objects","type":"hasLabel","value":true},{"label":"JS Evaluation","type":"hasLabel","value":true},{"label":"Custom JS Libraries","type":"hasLabel","value":true},{"label":"Action Selector","type":"hasLabel","value":true},{"label":"Widget setter method","type":"hasLabel","value":true},{"label":"Entity Refactor","type":"hasLabel","value":true},{"label":"AST-frontend","type":"hasLabel","value":true},{"label":"Sniping Mode","type":"hasLabel","value":true},{"label":"AST-backend","type":"hasLabel","value":true}],"requires":1},"IDE Product":{"conditions":[{"label":"IDE Product","type":"hasLabel","value":true},{"label":"IDE Infra","type":"hasLabel","value":true},{"label":"IDE Navigation","type":"hasLabel","value":true},{"label":"IDE tabs","type":"hasLabel","value":true},{"label":"Omnibar","type":"hasLabel","value":true},{"label":"Entity Explorer","type":"hasLabel","value":true},{"label":"Page Management","type":"hasLabel","value":true},{"label":"Preview mode","type":"hasLabel","value":true},{"label":"Entity Management","type":"hasLabel","value":true}],"requires":1},"Accelerators Product":{"conditions":[{"label":"Generate Page","type":"hasLabel","value":true},{"label":"Building blocks","type":"hasLabel","value":true}],"requires":1},"Templates Product":{"conditions":[{"label":"Partial-import-export","type":"hasLabel","value":true},{"label":"Templates Product","type":"hasLabel","value":true}],"requires":1},"Design System Product":{"conditions":[{"label":"Design System Product","type":"hasLabel","value":true},{"label":"ADS Component Issue","type":"hasLabel","value":true},{"label":"Keyboard accessibility ","type":"hasLabel","value":true},{"label":"Toggle button","type":"hasLabel","value":true},{"label":"ADS Category Token","type":"hasLabel","value":true},{"label":"ADS Component Documentation","type":"hasLabel","value":true},{"label":"ADS Migration","type":"hasLabel","value":true},{"label":"ADS Deduplication ","type":"hasLabel","value":true},{"label":"ADS Revamp","type":"hasLabel","value":true},{"label":"ADS Deduplication","type":"hasLabel","value":true},{"label":"ADS Unit Test","type":"hasLabel","value":true},{"label":"ADS Components","type":"hasLabel","value":true},{"label":"ADS Grayscale","type":"hasLabel","value":true},{"label":"Design System","type":"hasLabel","value":true},{"label":"ADS Typography","type":"hasLabel","value":true},{"label":"ADS Visual Styles","type":"hasLabel","value":true},{"label":"ADS Component Design","type":"hasLabel","value":true},{"label":"Modal Component","type":"hasLabel","value":true},{"label":"ADS Spacing","type":"hasLabel","value":true},{"label":"ads unit test","type":"hasLabel","value":true},{"label":"ads revamp","type":"hasLabel","value":true},{"label":"ads deduplication","type":"hasLabel","value":true}],"requires":1},"RBAC Product":{"conditions":[{"label":"Invite users","type":"hasLabel","value":true},{"label":"RBAC Product","type":"hasLabel","value":true}],"requires":1},"Workspace Product":{"conditions":[{"label":"Home Page","type":"hasLabel","value":true},{"label":"Workspace Product","type":"hasLabel","value":true}],"requires":1},"Billing & Licensing Product":{"conditions":[{"label":"Customer Portal","type":"hasLabel","value":true},{"label":"Cloud Services","type":"hasLabel","value":true},{"label":"Billing","type":"hasLabel","value":true},{"label":"Self Serve","type":"hasLabel","value":true},{"label":"Enterprise Billing","type":"hasLabel","value":true},{"label":"Analytics Improvements","type":"hasLabel","value":true},{"label":"Self Serve 1.0","type":"hasLabel","value":true},{"label":"License","type":"hasLabel","value":true},{"label":"BE instance","type":"hasLabel","value":true},{"label":"Invite flow","type":"hasLabel","value":true},{"label":"CE Instance Usage","type":"hasLabel","value":true},{"label":"Feature Flagging","type":"hasLabel","value":true}],"requires":1},"Packages Product":{"conditions":[{"label":"Packages Product","type":"hasLabel","value":true}],"requires":1},"Environments Product":{"conditions":[{"label":"Environments Product","type":"hasLabel","value":true}],"requires":1},"UI Building Product":{"conditions":[{"label":"Property Pane","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":"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":"Canvas / Grid","type":"hasLabel","value":true},{"label":"Auto Height","type":"hasLabel","value":true},{"label":"Browser specific","type":"hasLabel","value":true},{"label":"Auto Layout","type":"hasLabel","value":true},{"label":"Fixed layout","type":"hasLabel","value":true},{"label":"App Navigation","type":"hasLabel","value":true}],"requires":1},"Onboarding Product":{"conditions":[{"label":"Welcome Screen","type":"hasLabel","value":true}],"requires":1},"Git Product":{"conditions":[{"label":"Git Product","type":"hasLabel","value":true},{"label":"Git Auto-commit","type":"hasLabel","value":true},{"label":"Auto-commit","type":"hasLabel","value":true},{"label":"Continuous Deployment","type":"hasLabel","value":true},{"label":"Default branch","type":"hasLabel","value":true},{"label":"Git status","type":"hasLabel","value":true},{"label":"Git performance","type":"hasLabel","value":true},{"label":"SDLC","type":"hasLabel","value":true},{"label":"Git IA","type":"hasLabel","value":true},{"label":"Branch management","type":"hasLabel","value":true}],"requires":1},"Embedding Apps Product":{"conditions":[{"label":"Embedding Apps Product","type":"hasLabel","value":true}],"requires":1},"Integrations Product":{"conditions":[{"label":"New Datasource","type":"hasLabel","value":true},{"label":"Firestore","type":"hasLabel","value":true},{"label":"Google Sheets","type":"hasLabel","value":true},{"label":"Mongo","type":"hasLabel","value":true},{"label":"Redshift","type":"hasLabel","value":true},{"label":"snowflake","type":"hasLabel","value":true},{"label":"S3","type":"hasLabel","value":true},{"label":"Redis","type":"hasLabel","value":true},{"label":"Postgres","type":"hasLabel","value":true},{"label":"GraphQL Plugin","type":"hasLabel","value":true},{"label":"ArangoDB","type":"hasLabel","value":true},{"label":"MsSQL","type":"hasLabel","value":true},{"label":"Elastic Search","type":"hasLabel","value":true},{"label":"OAuth","type":"hasLabel","value":true},{"label":"Airtable","type":"hasLabel","value":true},{"label":"CURL","type":"hasLabel","value":true},{"label":"DynamoDB","type":"hasLabel","value":true},{"label":"Zendesk","type":"hasLabel","value":true},{"label":"Hubspot","type":"hasLabel","value":true},{"label":"Query Forms","type":"hasLabel","value":true},{"label":"Twilio","type":"hasLabel","value":true},{"label":"MySQL","type":"hasLabel","value":true},{"label":"Connection pool","type":"hasLabel","value":true},{"label":"MariaDB","type":"hasLabel","value":true},{"label":"Integrations Pod General","type":"hasLabel","value":true},{"label":"SMTP plugin","type":"hasLabel","value":true},{"label":"Oracle SQL DB","type":"hasLabel","value":true},{"label":"Query filter","type":"hasLabel","value":true},{"label":"Activation - datasources","type":"hasLabel","value":true},{"label":"REST API","type":"hasLabel","value":true},{"label":"REST API","type":"hasLabel","value":true},{"label":"Datasources","type":"hasLabel","value":true},{"label":"REST API plugin","type":"hasLabel","value":true},{"label":"Prepared statements","type":"hasLabel","value":true},{"label":"Query Generation","type":"hasLabel","value":true},{"label":"Core Query Execution","type":"hasLabel","value":true},{"label":"Query Management","type":"hasLabel","value":true},{"label":"Query Settings","type":"hasLabel","value":true},{"label":"Query performance","type":"hasLabel","value":true},{"label":"Datatype issue","type":"hasLabel","value":true},{"label":"SmartSubstitution","type":"hasLabel","value":true},{"label":"Suggested Widgets","type":"hasLabel","value":true},{"label":"SAAS Plugins","type":"hasLabel","value":true},{"label":"Reconnect DS modal","type":"hasLabel","value":true},{"label":"OnPageLoad","type":"hasLabel","value":true},{"label":"File upload issues","type":"hasLabel","value":true},{"label":"AI","type":"hasLabel","value":true},{"label":"Appsmith AI","type":"hasLabel","value":true},{"label":"Database Schema","type":"hasLabel","value":true}],"requires":1},"Identity & Authentication Product":{"conditions":[{"label":"Login / Signup","type":"hasLabel","value":true},{"label":"SSO","type":"hasLabel","value":true},{"label":"SCIM","type":"hasLabel","value":true},{"label":"Email verification","type":"hasLabel","value":true}],"requires":1},"Artifact Platform Product":{"conditions":[{"label":"Fork App","type":"hasLabel","value":true},{"label":"Publish App","type":"hasLabel","value":true},{"label":"Secret Management","type":"hasLabel","value":true},{"label":"Import-Export-App","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},{"label":"Backup & Restore","type":"hasLabel","value":true},{"label":"AWS AMI","type":"hasLabel","value":true},{"label":"Observability","type":"hasLabel","value":true},{"label":"Heroku","type":"hasLabel","value":true},{"label":"New Deployment Mode","type":"hasLabel","value":true},{"label":"Supervisor","type":"hasLabel","value":true},{"label":"Deployment Certificates","type":"hasLabel","value":true},{"label":"Mock Data","type":"hasLabel","value":true},{"label":"AWS ECS","type":"hasLabel","value":true},{"label":"Ingress","type":"hasLabel","value":true},{"label":"Nginx","type":"hasLabel","value":true},{"label":"Setup Issues","type":"hasLabel","value":true}],"requires":1},"Performance Pod":{"conditions":[{"label":"Performance","type":"hasLabel","value":true},{"label":"Performance infra","type":"hasLabel","value":true}],"requires":1},"IDE Pod":{"conditions":[{"label":"Telemetry","type":"hasLabel","value":true},{"label":"i18n","type":"hasLabel","value":true},{"label":"IDE Product","type":"hasLabel","value":true},{"label":"App setting","type":"hasLabel","value":true},{"label":"Debugger Product","type":"hasLabel","value":true},{"label":"Embedding Apps Product","type":"hasLabel","value":true}],"requires":1},"Platform Administration Pod":{"conditions":[{"label":"Airgap","type":"hasLabel","value":true},{"label":"Enterprise Edition","type":"hasLabel","value":true},{"label":"Invite flow","type":"hasLabel","value":true},{"label":"User Profile","type":"hasLabel","value":true},{"label":"User Session ","type":"hasLabel","value":true},{"label":"User Session","type":"hasLabel","value":true},{"label":"Admin Settings Product","type":"hasLabel","value":true},{"label":"RBAC Product","type":"hasLabel","value":true},{"label":"Workspace Product","type":"hasLabel","value":true},{"label":"Branding Product","type":"hasLabel","value":true},{"label":"Audit Logs Product","type":"hasLabel","value":true},{"label":"Identity & Authentication Product","type":"hasLabel","value":true},{"label":"Billing & Licensing Product","type":"hasLabel","value":true},{"label":"Move to Postgres","type":"hasLabel","value":true},{"label":"Cloud Billing","type":"hasLabel","value":true}],"requires":1},"DB Infrastructure Pod":{"conditions":[],"requires":1},"Widgets & Accelerators Pod":{"conditions":[{"label":"Accelerators Product","type":"hasLabel","value":true},{"label":"Templates Product","type":"hasLabel","value":true},{"label":"Widgets Product","type":"hasLabel","value":true},{"label":"App Theming Product","type":"hasLabel","value":true}],"requires":1},"Packages Pod":{"conditions":[{"label":"Module creator","type":"hasLabel","value":true},{"label":"Module consumer","type":"hasLabel","value":true},{"label":"Package versioning","type":"hasLabel","value":true},{"label":"Convert to module","type":"hasLabel","value":true},{"label":"Query module","type":"hasLabel","value":true},{"label":"JS module","type":"hasLabel","value":true},{"label":"UI module","type":"hasLabel","value":true},{"label":"Packages Pod","type":"hasLabel","value":true}],"requires":1},"Workflows Pod":{"conditions":[{"label":"Workflows Product","type":"hasLabel","value":true}],"requires":1},"Query & JS Pod":{"conditions":[{"label":"Javascript Product","type":"hasLabel","value":true},{"label":"Onboarding Product","type":"hasLabel","value":true},{"label":"Integrations Product","type":"hasLabel","value":true},{"label":"Reconfigure Datasource Modal","type":"hasLabel","value":true}],"requires":1},"QA Pod":{"conditions":[{"label":"Automation Test","type":"hasLabel","value":true},{"label":"TestGap","type":"hasLabel","value":true},{"label":"Automation failures","type":"hasLabel","value":true},{"label":"Needs automation","type":"hasLabel","value":true},{"label":"cypress-flaky-fix","type":"hasLabel","value":true},{"label":"Cypress flaky tests","type":"hasLabel","value":true},{"label":"Cypress","type":"hasLabel","value":true}],"requires":1},"Anvil POD":{"conditions":[{"label":"Checkbox Component","type":"hasLabel","value":true},{"label":"WDS team","type":"hasLabel","value":true},{"label":"Anvil POD","type":"hasLabel","value":true},{"label":"WDS - all widgets","type":"hasLabel","value":true},{"label":"WDS - input widget","type":"hasLabel","value":true},{"label":"WDS - paragraph widget","type":"hasLabel","value":true},{"label":"WDS - statbox widget","type":"hasLabel","value":true},{"label":"WDS - modal widget","type":"hasLabel","value":true},{"label":"WDS - icon widget","type":"hasLabel","value":true},{"label":"WDS - checkbox widget","type":"hasLabel","value":true},{"label":"WDS - table widget","type":"hasLabel","value":true},{"label":"WDS - keyValue widget","type":"hasLabel","value":true},{"label":"WDS - switch group widget","type":"hasLabel","value":true},{"label":"WDS - theming","type":"hasLabel","value":true},{"label":"Anvil layout","type":"hasLabel","value":true},{"label":"Anvil - theming","type":"hasLabel","value":true},{"label":"Anvil - vertical alignment","type":"hasLabel","value":true},{"label":"Anvil - layout component","type":"hasLabel","value":true},{"label":"Anvil - drag & drop","type":"hasLabel","value":true},{"label":"Anvil - zones & sections","type":"hasLabel","value":true},{"label":"Anvil - copy paste experience","type":"hasLabel","value":true},{"label":"WDS - phone widget","type":"hasLabel","value":true},{"label":"WDS - responsive widget","type":"hasLabel","value":true},{"label":"Anvil - responsive viewport","type":"hasLabel","value":true},{"label":"WDS - widget styling","type":"hasLabel","value":true},{"label":"Anvil - spacing","type":"hasLabel","value":true},{"label":"Anvil - responsive canvas","type":"hasLabel","value":true},{"label":"WDS - inline button widget","type":"hasLabel","value":true},{"label":"Anvil team","type":"hasLabel","value":true}],"requires":1},"Activation Pod":{"conditions":[{"label":"Activation","type":"hasLabel","value":true}],"requires":1},"Stability Pod":{"conditions":[{"label":"Stability Issue","type":"hasLabel","value":true}],"requires":1},"Documentation Pod":{"conditions":[{"label":"Documentation","type":"hasLabel","value":true}],"requires":1},"Packages & Git Pod":{"conditions":[{"label":"Packages Pod","type":"hasLabel","value":true},{"label":"Git Product","type":"hasLabel","value":true},{"label":"Packages Product","type":"hasLabel","value":true},{"label":"Git Platform","type":"hasLabel","value":true}],"requires":1},"Git Platform":{"conditions":[{"label":"Environments Product","type":"hasLabel","value":true},{"label":"Artifact Platform Product","type":"hasLabel","value":true}],"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"},"Checkbox Group widget":{"color":"bbeecd","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":"748fda","name":"QA","description":"Needs QA attention"},"Verified":{"color":"9bf416","name":"Verified","description":""},"Wont Fix":{"color":"ffffff","name":"Wont Fix","description":"This will not be worked on"},"MySQL":{"color":"c9ddc6","name":"MySQL","description":"Issues related to MySQL plugin"},"Development":{"color":"9F8A02","name":"Development","description":""},"Help Wanted":{"color":"008672","name":"Help Wanted","description":"Extra attention is needed"},"Home Page":{"color":"","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"},"Fork App":{"color":"af87c7","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":""},"Needs Design":{"color":"bfd4f2","name":"Needs Design","description":"needs design or changes to design"},"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":""},"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":"8078b0","name":"Firestore","description":"Issues related to the firestore Integration"},"New Widget":{"color":"be4cf2","name":"New Widget","description":"A request for a new widget"},"Modal Widget":{"color":"03846f","name":"Modal Widget","description":""},"UX Improvement":{"color":"f4a089","name":"UX Improvement","description":""},"S3":{"color":"8078b0","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"},"Calendar Widget":{"color":"8c6644","name":"Calendar Widget","description":""},"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"},"Checkbox Widget":{"color":"bbeecd","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":"8ba6fd","name":"Bug","description":"Something isn't right"},"Widget Validation":{"color":"6990BC","name":"Widget Validation","description":"Issues related to widget property validation"},"Generate Page":{"color":"2b4664","name":"Generate Page","description":"Issures related to page generation"},"File Picker Widget":{"color":"6ae4f2","name":"File Picker Widget","description":""},"snowflake":{"color":"8078b0","name":"snowflake","description":"Issues related to the snowflake Integration"},"Automation":{"color":"CCAF60","name":"Automation","description":""},"hotfix":{"color":"BA3F1D","name":"hotfix","description":""},"Import-Export-App":{"color":"48883f","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"},"Telemetry":{"color":"bc70f9","name":"Telemetry","description":"Issues related to instrumenting appsmith"},"Radio Widget":{"color":"91ef15","name":"Radio Widget","description":""},"Omnibar":{"color":"1bb96a","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":""},"Task":{"color":"085630","name":"Task","description":"A simple Todo"},"Design System":{"color":"2958a4","name":"Design System","description":"Design system"},"opera":{"color":"C63F5B","name":"opera","description":"Any issues identified on the opera browser"},"Login / Signup":{"color":"","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"},"Production":{"color":"b60205","name":"Production","description":""},"Dependencies":{"color":"0366d6","name":"Dependencies","description":"Pull requests that update a dependency file"},"Google Sheets":{"color":"8078b0","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":"8078b0","name":"Mongo","description":"Issues related to Mongo DB plugin"},"Documentation":{"color":"a8dff7","name":"Documentation","description":"Improvements or additions to documentation"},"TestGap":{"color":"","name":"TestGap","description":"Issues identified for test plan improvement"},"keyboard shortcut":{"color":"0688B6","name":"keyboard shortcut","description":""},"Reopen":{"color":"897548","name":"Reopen","description":""},"Redshift":{"color":"8078b0","name":"Redshift","description":"Issues related to the redshift integration"},"Date Picker Widget":{"color":"ef1ce1","name":"Date Picker Widget","description":""},"Entity Explorer":{"color":"1bb96a","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},"Text Widget":{"color":"d130d1","name":"Text Widget","description":""},"Video Widget":{"color":"23dd4b","name":"Video Widget","description":""},"Datasources":{"color":"3d590f","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"},"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"},"UI Performance":{"color":"1799b0","name":"UI Performance","description":"Issues related to UI performance"},"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"},"Chart Widget":{"color":"616ecc","name":"Chart Widget","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"},"Sniping Mode":{"name":"Sniping Mode","description":"Issues related to sniping mode","color":"48883f"},"Redis":{"name":"Redis","description":"Issues related to Redis","color":"8078b0"},"New Datasource":{"color":"60b14c","name":"New Datasource","description":"Requests for new datasources"},"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":"4773ab"},"Widgets Pane":{"name":"Widgets Pane","description":"Issues related to the discovery and organisation of widgets","color":"ad5d78"},"View Mode":{"color":"1799b0","name":"View Mode","description":"Issues related to the view mode"},"Content":{"name":"Content","description":"For content related topics i.e blogs, templates, videos","color":"a8dff7"},"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":"8078b0"},"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":"e6038e"},"SAAS Plugins":{"name":"SAAS Plugins","description":"Issues related to SAAS Plugins","color":"80e18f"},"JS Promises":{"name":"JS Promises","description":"Issues related to promises","color":"d7771f"},"OnPageLoad":{"name":"OnPageLoad","description":"OnPageLoad issues on functions and queries","color":"2b4664"},"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":"48883f"},"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"},"Reflow & Resize":{"name":"Reflow & Resize","description":"All issues related to reflow and resize experience","color":"748a13"},"SSO":{"name":"SSO","description":"Issues, requests and enhancements around Single sign-on.","color":""},"Multi User Realtime":{"name":"Multi User Realtime","description":"Issues related to multiple users using or editing an application","color":"e7b6ce"},"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":"8078b0"},"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":"8078b0"},"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":"60885f"},"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":"60885f"},"Canvas Zooms":{"name":"Canvas Zooms","description":"Issues related to zooming the canvas","color":"e6038e"},"business":{"name":"business","description":"Features that will be a part of our business edition","color":"cd59eb"},"Action Pod":{"name":"Action Pod","description":"","color":"ee2e36"},"AutomationGap1":{"color":"a5e07c","name":"AutomationGap1","description":"Issues that needs automated tests"},"A-Force11":{"name":"A-Force11","description":"Issues raised by A-Force team","color":"d667b6"},"Business Edition":{"name":"Business Edition","description":"Features that will be a part of our business edition","color":"89bb6c"},"storeValue":{"name":"storeValue","description":"Issues related to the store value function","color":"5d3e66"},"DynamoDB":{"name":"DynamoDB","description":"Issues that are related to DynamoDB should have this label","color":"60885f"},"Backup & Restore":{"name":"Backup & Restore","description":"Issues related to backup and restore","color":"86874d"},"Billing":{"name":"Billing","description":"Billing infrastructure and flows for Business Edition and Trial users","color":"d2bc40"},"Datatype issue":{"name":"Datatype issue","description":"Issues that have risen because data types weren't handled","color":"cef66b"},"OAuth":{"name":"OAuth","description":"OAuth related bugs or features","color":"60885f"},"Table Widget V2":{"name":"Table Widget V2","description":"Issues related to Table Widget V2","color":"3a7192"},"IDE Navigation":{"name":"IDE Navigation","description":"Issues/feature requests related to IDE navigation, and context switching","color":"1bb96a"},"Query performance":{"name":"Query performance","description":"Issues that have to do with lack in performance of query execution","color":"cef66b"},"SAAS Manager App":{"name":"SAAS Manager App","description":"Issues with the SAAS manager app","color":"d427db"},"Twilio":{"name":"Twilio","description":"Issues related to Twilio integration","color":"23ba8d"},"Hubspot":{"name":"Hubspot","description":"Issues related to Hubspot integration","color":"60885f"},"Zendesk":{"name":"Zendesk","description":"Issues related to Zendesk integration","color":"60885f"},"Entity Refactor":{"name":"Entity Refactor","description":"Issues related to refactor logic","color":"705a2c"},"Map Chart Widget":{"name":"Map Chart Widget","description":"Issues related to Map Chart Widgets","color":"c8397f"},"Product Catchup":{"name":"Product Catchup","description":"Issues created in the product catchup","color":"29cd2c"},"Framework Functions":{"name":"Framework Functions","description":"Issues related to internal functions like showAlert(), navigateTo() etc...","color":"c25a09"},"Frontend Libraries Upgrade":{"name":"Frontend Libraries Upgrade","description":"Issues related to frontend libraries upgrade","color":"ede1fc"},"MsSQL":{"name":"MsSQL","description":"Issues related to MsSQL plugin","color":"8078b0"},"Elastic Search":{"name":"Elastic Search","description":"Issues related to the elastic search datasource","color":"8078b0"},"Core Query Execution":{"color":"cef66b","name":"Core Query Execution","description":"Issues related to the execution of all queries"},"Query Management":{"name":"Query Management","description":"Issues related to the CRUD of actions or queries","color":"cef66b"},"Query Settings":{"name":"Query Settings","description":"Issues related to the settings of all queries","color":"cef66b"},"Code Editor":{"name":"Code Editor","description":"Issues related to the code editor","color":"4ca16e"},"Query Forms":{"color":"12b253","name":"Query Forms","description":"Isuses related to the query forms"},"JS Objects":{"color":"22962c","name":"JS Objects","description":"Issues related to JS Objects"},"JS Evaluation":{"color":"22962c","name":"JS Evaluation","description":"Issues related to JS evaluation on the platform"},"SmartSubstitution":{"name":"SmartSubstitution","description":"Issues related to Smart substitution of mustache bindings in queries","color":"bae511"},"Query Generation":{"name":"Query Generation","description":"Issues related to query generation","color":"cef66b"},"Suggested Widgets":{"name":"Suggested Widgets","description":"Issues related to suggesting widgets based on query response","color":"6ac063"},"Code Scanner Widget":{"name":"Code Scanner Widget","description":"Issues related to code scanner widget","color":"9bc1a0"},"Clean URLs":{"name":"Clean URLs","description":"Issues related to clean URLs epic","color":"112623"},"Widget keyboard accessibility":{"name":"Widget keyboard accessibility","description":"All issues related to keyboard accessibility in widgets","color":"b626fd"},"Connection pool":{"name":"Connection pool","description":"issues to do with connection pooling of various plugins","color":"94fe36"},"List Widget V2":{"name":"List Widget V2","description":"Issues related to the list widget v2","color":"adaaf7"},"Auto Height":{"name":"Auto Height","description":"Issues related to dynamic height of widgets","color":"5149cf"},"cypress_failed_test":{"name":"cypress_failed_test","description":"Cypress failed tests","color":"4745d5"},"Needs validation":{"name":"Needs validation","description":"Needs problem validation before being picked up","color":"66673d"},"Slider Widget":{"name":"Slider Widget","description":"Issues raised for slider widgets.","color":"2eef5f"},"Multitenancy":{"name":"Multitenancy","description":"Support multitenancy within single appsmith instance","color":"8c49a9"},"Conversion Algorithm":{"name":"Conversion Algorithm","description":"All issue related to converting app from fixed to flex mode & vice versa","color":"d12d2e"},"Browser specific":{"name":"Browser specific","description":"All issue related to browser","color":"d12d2e"},"Performance infra":{"name":"Performance infra","description":"all issue related to the performance infra","color":"8a60f6"},"DSL Update":{"name":"DSL Update","description":"Issues related to storing and updating the DSL","color":"e16cf3"},"AST-frontend":{"name":"AST-frontend","description":"Issues related to maintaining AST logic","color":"2b4664"},"AST-backend":{"name":"AST-backend","description":"Backend issues related to AST parsing","color":"48883f"},"MariaDB":{"name":"MariaDB","description":"MariaDB datasource","color":"8428c3"},"ADS Component Issue":{"name":"ADS Component Issue","description":"Issues which are caused due to ADS components","color":"d89119"},"Regressed":{"color":"723fd0","name":"Regressed","description":"Scenarios that were working before but have now regressed"},"Needs RCA":{"name":"Needs RCA","description":"a critical or high priority issue that needs an RCA","color":"2cc68f"},"Custom JS Libraries":{"name":"Custom JS Libraries","description":"Issues related to adding custom JS library","color":"bacb6d"},"Integrations Pod General":{"name":"Integrations Pod General","description":"Issues related to the Integrations Pod that don't fit into other tags.","color":"287823"},"Performance Pod":{"name":"Performance Pod","description":"All things related to Appsmith performance","color":"b5a25d"},"Performance":{"name":"Performance","description":"Issues related to performance","color":"9a18d7"},"File upload issues":{"name":"File upload issues","description":"Issues related to uploading any type of files from within Appsmith","color":"2b4664"},"Action Selector":{"name":"Action Selector","description":"Issues related to action selector on the property pane","color":"2f9e20"},"Community Reported":{"name":"Community Reported","description":"issues reported by community members","color":"1402e5"},"JS Function execution":{"name":"JS Function execution","description":"JS function execution","color":"7c2de1"},"Self Serve":{"name":"Self Serve","description":"For all issues related to self-serve flow for business edition","color":"4dacfc"},"Self Serve 1.0":{"name":"Self Serve 1.0","description":"For all issues related to v1 of the self serve project","color":"ae839e"},"Customer Portal":{"name":"Customer Portal","description":"For all tasks/issues pertaining to customer.appsmith.com","color":"d2bc40"},"Cloud Services":{"name":"Cloud Services","description":"For all tasks/issues on Appsmith cloud-services relating to licensing, usage and billing","color":"d2bc40"},"One-click Binding":{"name":"One-click Binding","description":"Issues related to the One click binding epic","color":"f1661c"},"Airgap":{"name":"Airgap","description":"Tickets related to supporting air-gapped Appsmith instances","color":"1cb294"},"SMTP plugin":{"name":"SMTP plugin","description":"Issues related to SMTP plugin","color":"541457"},"AWS AMI":{"name":"AWS AMI","description":"Issues Related to AWS AMI","color":"b44680"},"Old widget version":{"name":"Old widget version","description":"Use this label to raise issue specific only to an older version of a widget","color":"ff3814"},"Enterprise Billing":{"name":"Enterprise Billing","description":"To track all tasks/issues related to licensing & billing for enterprise customers","color":"14c156"},"Oracle SQL DB":{"name":"Oracle SQL DB","description":"Issues related to the Oracle plugin","color":"cbabcb"},"Community Contributor":{"name":"Community Contributor","description":"Meant to track issues that are assigned to external contributors","color":"149ab6"},"widget vertical alignment":{"name":"widget vertical alignment","description":"All issue related widget vertical alignment on the auto layout canvas","color":"d12d2e"},"Observability":{"name":"Observability","description":"Issues related to observability on the Appsmith instance","color":"dff913"},"Checkbox Component":{"name":"Checkbox Component","description":"This labels deals with checkbox component in wds package","color":"75a401"},"Analytics Improvements":{"name":"Analytics Improvements","description":"For all tasks focused on improving our overall analytics and fixing any issues ","color":"29b8ed"},"WDS team":{"name":"WDS team","description":"","color":"8d675a"},"Enterprise Edition":{"name":"Enterprise Edition","description":"Features that will be supported in Enterprise Edition only","color":"984f5e"},"Query filter":{"name":"Query filter","description":"Issues related to query filtering, e.g., WHERE clause","color":"a15134"},"Keyboard accessibility ":{"name":"Keyboard accessibility ","description":"All issue related to ADS component keyboard accessibility","color":"2ba696"},"Toggle button":{"name":"Toggle button","description":"All issue related to ADS toggle button","color":"edc47f"},"SCIM":{"name":"SCIM","description":"Label to collate our SCIM issues","color":"48883f"},"ADS Category Token":{"name":"ADS Category Token","description":"All issues related appsmith design system category tokens","color":"920961"},"ADS Component Documentation":{"name":"ADS Component Documentation","description":"All issues Appsmith design system component documentation","color":"64c46a"},"ADS Migration":{"name":"ADS Migration","description":"All issues related to Appsmith design system migration","color":"b082d6"},"ADS Deduplication ":{"name":"ADS Deduplication ","description":"Replacing component with ADS components","color":"b082d6"},"ADS Revamp":{"name":"ADS Revamp","description":"All issues related to ads revamp. ","color":"b082d6"},"ADS Deduplication":{"name":"ADS Deduplication","description":"Replacing component with ADS components","color":"b082d6"},"ADS Grayscale":{"name":"ADS Grayscale","description":"Support grayscale color changes","color":"b03577"},"ADS Unit Test":{"name":"ADS Unit Test","description":"All issue related ads unit cases ","color":"b082d6"},"ADS Components":{"name":"ADS Components","description":"All issues related ADS components","color":"b082d6"},"Widget Discoverability":{"name":"Widget Discoverability","description":"Issues related to Widget Discoverability","color":"7b55ce"},"Widget setter method":{"name":"Widget setter method","description":"Issues with widget property setters","color":"8dce87"},"License":{"name":"License","description":"For all issues/tasks related to licensing of appsmith-ee edition","color":"90ee98"},"Platformization":{"name":"Platformization","description":"Issues or tasks related to platformization of Appsmith codebase","color":"4e972b"},"Activation - datasources":{"name":"Activation - datasources","description":"issues related to activation projects","color":"7c7ace"},"Partial-import-export":{"name":"Partial-import-export","description":"Label for granular reusability.","color":"717732"},"AI":{"name":"AI","description":"All tasks related to AI","color":"2b4664"},"ADS Typography":{"name":"ADS Typography","description":"All issue related typographical changes","color":"2dbe8d"},"Auto Layout":{"name":"Auto Layout","description":"Issues relates to auto layout","color":"92cf8c"},"Heroku":{"name":"Heroku","description":"Issues related to Heroku","color":"a81b69"},"ADS Visual Styles":{"name":"ADS Visual Styles","description":"All issues related to ADS visual styles","color":"d3da89"},"ADS Component Design":{"name":"ADS Component Design","description":"All issue related to component design","color":"5cc91e"},"Modal Component":{"name":"Modal Component","description":"All issue related to ads modal component","color":"ee63f3"},"App setting":{"name":"App setting","description":"Related to app settings panel within the app","color":"174f98"},"BE instance":{"name":"BE instance","description":"For all issues related to license, billing on BE instance","color":"ae8f98"},"Fixed layout":{"name":"Fixed layout","description":"issues related to fixed layout","color":"b66681"},"Anvil layout":{"name":"Anvil layout","description":"issues related to the new layout system anvil","color":"5e0904"},"New Deployment Mode":{"name":"New Deployment Mode","description":"Support a new mode of deployment","color":"108033"},"Custom widgets":{"name":"Custom widgets","description":"For all issues related to the custom widget project","color":"c9db9c"},"Homepage Experience V2":{"name":"Homepage Experience V2","description":"Label for reporting new tasks and bug fixes related to revamped homepage experience","color":"c55d54"},"Customer Success":{"name":"Customer Success","description":"Issues that the success team cares about","color":"6ccabd"},"Invite flow":{"name":"Invite flow","description":"Invite users flow and any associated actions","color":"881b35"},"Invite users":{"name":"Invite users","description":"Invite users flow and any associated actions","color":""},"Workflows Pod":{"name":"Workflows Pod","description":"Issues that the workflows team owns","color":"446925"},"DailyPromotionBlocker":{"name":"DailyPromotionBlocker","description":"DailyPromotion Blocker","color":"9b2280"},"JS Binding":{"name":"JS Binding","description":"All issues related to the JS Binding experience","color":"422fed"},"REST API":{"name":"REST API","description":"REST API plugin related issues","color":"e3ede5"},"Critical":{"color":"a1e3db","name":"Critical","description":"This issue breaks existing apps. Drop everything else to resolve"},"Module creator":{"name":"Module creator","description":"Issues related to the module creator side","color":"bb2c05"},"Module consumer":{"name":"Module consumer","description":"Issues related to the module consumer side","color":"83d3c5"},"Package versioning":{"name":"Package versioning","description":"ISsues related to how we manage versions for packages","color":"4c5218"},"Convert to module":{"name":"Convert to module","description":"Issues related to the module creation flow using conversion","color":"4c5218"},"Query module":{"name":"Query module","description":"Issues affecting query modules or its instances","color":"b11a7e"},"JS module":{"name":"JS module","description":"Issues affecting JS modules or its instances","color":"bf76f6"},"Secret Management":{"name":"Secret Management","description":"Issues related to secret management","color":"2b4664"},"REST API plugin":{"name":"REST API plugin","description":"REST API plugin related issues","color":"b5948a"},"UI module":{"name":"UI module","description":"Issues affecting UI modules or its instances","color":"d2acee"},"Preview mode":{"name":"Preview mode","description":"Issues related to app previews","color":"48883f"},"Git Auto-commit":{"name":"Git Auto-commit","description":"Issues related to autocommit","color":"717732"},"QA Pod":{"name":"QA Pod","description":"Issues under the QA Pod","color":"717732"},"Automation Test":{"name":"Automation Test","description":"","color":""},"Automation failures":{"name":"Automation failures","description":"","color":""},"Needs automation":{"name":"Needs automation","description":"Issues that needs automated tests","color":""},"Prepared statements":{"name":"Prepared statements","description":"Issues related to prepared statement flow","color":""},"Switch Group Widget":{"name":"Switch Group Widget","description":"Issues related to Switch group Widget","color":""},"Supervisor":{"name":"Supervisor","description":"Issues related to supervisor","color":"2c5813"},"Deployment Certificates":{"name":"Deployment Certificates","description":"Issues related to lets encrypt","color":"e148aa"},"Mock Data":{"name":"Mock Data","description":"Issues related to mock databases","color":"ebf251"},"AWS ECS":{"name":"AWS ECS","description":"Issues related to ECS Fargate","color":"e506ff"},"Publish App":{"name":"Publish App","description":"Issues related to app deployment","color":"2b4664"},"IDE Infra":{"name":"IDE Infra","description":"Issues related to the IDE infrastructure like saving changes","color":"1bb96a"},"User Profile":{"name":"User Profile","description":"Issues related to a user profile","color":"a60d34"},"Page Management":{"color":"1bb96a","name":"Page Management","description":"Issues related to configuring pages"},"Ingress":{"name":"Ingress","description":"Ingress Controller","color":"a86802"},"Nginx":{"name":"Nginx","description":"Issues related to Nginx","color":"e54195"},"Building blocks":{"name":"Building blocks","description":"Building blocks on cavas, on templates listing or drag and drop of building blocks.","color":"48883f"},"Table Inline Edit":{"name":"Table Inline Edit","description":"Issues related to inline editing","color":"60895a"},"User Session ":{"name":"User Session ","description":"For all issues/tasks related to user sessions","color":"65a3f5"},"WDS - all widgets":{"name":"WDS - all widgets","description":"all widget present in WDS","color":"2670ae"},"WDS - input widget":{"name":"WDS - input widget","description":"Issues related to input widget on WDS","color":"2670ae"},"WDS - paragraph widget":{"name":"WDS - paragraph widget","description":"issues related to paragraph widget on WDS","color":"2670ae"},"WDS - statbox widget":{"name":"WDS - statbox widget","description":"issues related to statbox widget on WDS","color":"2670ae"},"WDS - modal widget":{"name":"WDS - modal widget","description":"Issues related to modal widget on WDS","color":"2670ae"},"WDS - icon widget":{"name":"WDS - icon widget","description":"Issues related to icon widget on WDS","color":"2670ae"},"WDS - checkbox widget":{"name":"WDS - checkbox widget","description":"Issues related to checkbox widget on WDS","color":"2670ae"},"WDS - table widget":{"name":"WDS - table widget","description":"Issues related to table widget on WDS","color":"2670ae"},"WDS - keyValue widget":{"name":"WDS - keyValue widget","description":"Issues related to key-value widget on WDS","color":"2670ae"},"WDS - switch group widget":{"name":"WDS - switch group widget","description":"Issues related to switch group widget on WDS","color":"2670ae"},"WDS - theming":{"name":"WDS - theming","description":"Issues related to theming on the Anvil instance","color":"2670ae"},"Anvil POD":{"name":"Anvil POD","description":"Issue related to Anvil project","color":"5e0904"},"Anvil - theming":{"name":"Anvil - theming","description":"Issues related to theming on the Anvil instance","color":"c28de5"},"Anvil - vertical alignment":{"name":"Anvil - vertical alignment","description":"Issues related to vertical alignment on the Anvil layout","color":"c28de5"},"Anvil - layout component":{"name":"Anvil - layout component","description":"Issues related to layout component on the Anvil layout","color":"c28de5"},"Anvil - drag & drop":{"name":"Anvil - drag & drop","description":"Issues related to drag & drop experience on Anvil","color":"c28de5"},"Anvil - zones & sections":{"name":"Anvil - zones & sections","description":"Issues related to zones and sections on the Anvil layout","color":"c28de5"},"Anvil - copy paste experience":{"name":"Anvil - copy paste experience","description":"Issues related to copy paste experience on the Anvil layout","color":"c28de5"},"WDS - phone widget":{"name":"WDS - phone widget","description":"Issues related to phone widget on WDS","color":"c28de5"},"WDS - responsive widget":{"name":"WDS - responsive widget","description":"All issues related to widget responsiveness","color":"11ee05"},"Anvil - responsive viewport":{"color":"11ee05","name":"Anvil - responsive viewport","description":"Issues seen on different viewports like mobile"},"WDS - widget styling":{"color":"11ee05","name":"WDS - widget styling","description":"all about widget styling"},"Anvil - spacing":{"name":"Anvil - spacing","description":"Related to spacing between widgets in auto layout","color":"11ee05"},"Anvil - responsive canvas":{"name":"Anvil - responsive canvas","description":"All issues related to canvas responsiveness","color":"11ee05"},"WDS - inline button widget":{"name":"WDS - inline button widget","description":"Issues related to inline button widget on WDS","color":"7cef83"},"Activation Pod":{"name":"Activation Pod","description":"for Activation group","color":"d67d00"},"Activation":{"name":"Activation","description":"for Activation group","color":"d67d00"},"Tests":{"name":"Tests","description":"Test issues","color":"4fc7b6"},"Ballpark: XXS":{"name":"Ballpark: XXS","description":"~1xDev in 1/2xSprint","color":""},"Ballpark: XS":{"name":"Ballpark: XS","description":"~1xDev in 1xSprint","color":"53bf71"},"Ballpark: S":{"name":"Ballpark: S","description":"~2xDev in 1xSprint","color":"6e9e65"},"Ballpark: M":{"name":"Ballpark: M","description":"~1xPOD in 1xSprint","color":"2229e6"},"Ballpark: L":{"name":"Ballpark: L","description":"~1xPOD in 3xSprint or 2xPODs in 1xSprint","color":"49962f"},"Ballpark: XL":{"name":"Ballpark: XL","description":"~1xPOD in 1xQuarter or 2xPODs in 2xSprint","color":"b524c9"},"Ballpark: XXL":{"name":"Ballpark: XXL","description":"~2xPODs in 1xQuarter","color":"22092c"},"Auto-commit":{"name":"Auto-commit","description":"Issues related to auto-generated commits showing up on git ","color":"e25b89"},"Continuous Deployment":{"name":"Continuous Deployment","description":"Issues related to CD pipeline on git","color":"aea47c"},"Default branch":{"name":"Default branch","description":"Issues related to using a default branch on git","color":"195737"},"Git status":{"name":"Git status","description":"Issues related to information shown on git status modal or number of changes appearing in a branch","color":"c851b8"},"Git performance":{"name":"Git performance","description":"Issues related to perceived performance on any git operation","color":"189af6"},"Anvil team":{"name":"Anvil team","description":"issues related to the new layout system anvil","color":"798200"},"SDLC":{"name":"SDLC","description":"Issues related to software development lifecycle experiences","color":"bae511"},"Reconnect DS modal":{"name":"Reconnect DS modal","description":"Issues related to reconnect datasource modal post app import","color":"2e398b"},"Stability Pod":{"name":"Stability Pod","description":"For all issues/tasks to be prioritized under Stability pod","color":"86ddf6"},"Stability Issue":{"name":"Stability Issue","description":"Every issue handle by Stability Pod","color":"4d024a"},"Move to Postgres":{"name":"Move to Postgres","description":"Issues required to be solved for the move to Postgres as repository layer","color":"466ab1"},"User Session":{"name":"User Session","description":"Issues related to user sessions","color":"8255e5"},"IDE tabs":{"name":"IDE tabs","description":"query and js tabs","color":"1bb96a"},"Inviting Contribution":{"name":"Inviting Contribution","description":"Issues that we would like contributions to","color":""},"cypress-flaky-fix":{"name":"cypress-flaky-fix","description":"This label is auto-added when a PR which only has Cypress fixes are merged to release","color":"cd8bb6"},"Cypress flaky tests":{"name":"Cypress flaky tests","description":"Test scripts that need to be fixed on Cypress by dev or SDET","color":"cd8bb6"},"Help enterprise":{"name":"Help enterprise","description":"Requested by Appsmith customers or prospects","color":"FF8C00"},"Learnability":{"name":"Learnability","description":"Issues affecting the product learnability, making the product harder for new users.","color":"800c2f"},"ADS Spacing":{"name":"ADS Spacing","description":"","color":"686ebb"},"ads unit test":{"name":"ads unit test","description":"All issue related ads unit cases","color":"686ebb"},"ads revamp":{"name":"ads revamp","description":"All issues related to ads revamp.","color":"686ebb"},"Javascript Product":{"color":"709a21","name":"Javascript Product","description":"Issues related to users writing javascript in appsmith"},"IDE Product":{"color":"1bb96a","name":"IDE Product","description":"Issues related to the IDE Product"},"IDE Pod":{"color":"1bb96a","name":"IDE Pod","description":"Issues that new developers face while exploring the IDE"},"Accelerators Product":{"name":"Accelerators Product","description":"Issues related to app building accelerators","color":"f3fce6"},"Templates Product":{"name":"Templates Product","description":"Issues related to Templates","color":"f3fce6"},"Design System Product":{"name":"Design System Product","description":"Appsmith design system related issues","color":"2b4664"},"ads deduplication":{"name":"ads deduplication","description":"Replacing component with ADS components","color":"708943"},"Admin Settings Product":{"color":"708943","name":"Admin Settings Product","description":"Issues in admin settings pages"},"Appsmith AI":{"name":"Appsmith AI","description":"All issues related to the Appsmith AI datasource","color":"708943"},"Query & JS Pod":{"color":"709a21","name":"Query & JS Pod","description":"Issues related to the query & JS Pod"},"RBAC Product":{"name":"RBAC Product","description":"Issues, requests and enhancements around RBAC.","color":""},"Workspace Product":{"name":"Workspace Product","description":"Issues related to workspaces","color":""},"CE Instance Usage":{"name":"CE Instance Usage","description":"For all issues relating to usage, licensing or billing on the CE instance","color":""},"Billing & Licensing Product":{"name":"Billing & Licensing Product","description":"Issues pertaining to licensing, billing and usage across self serve and enterprise customers","color":"466ab1"},"Platform Administration Pod":{"color":"446925","name":"Platform Administration Pod","description":"Issues related to platform administration & management"},"DB Infrastructure Pod":{"name":"DB Infrastructure Pod","description":"Pod to handle database infrastructure","color":"446925"},"Packages Product":{"name":"Packages Product","description":"Issues related to packages","color":"7e018f"},"Workflows Product":{"name":"Workflows Product","description":"Issues related to the workflows product","color":"446925"},"Debugger Product":{"color":"857f58","name":"Debugger Product","description":"Issues related to the debugger"},"Packages Pod":{"name":"Packages Pod","description":"issues that belong to the packages pod","color":"53742c"},"Environments Product":{"name":"Environments Product","description":"Issues related to datasource environments","color":"857f58"},"Custom Widgets":{"name":"Custom Widgets","description":"For all issues related to the custom widget project","color":"857f58"},"Branding Product":{"name":"Branding Product","description":"All issues under branding and whitelabelling appsmith ecosystem","color":"857f58"},"Widgets & Accelerators Pod":{"name":"Widgets & Accelerators Pod","description":"Issues related to widgets & Accelerators","color":"27496a"},"Widgets Product":{"name":"Widgets Product","description":"This label groups issues related to widgets","color":"f3fce6"},"App Theming Product":{"name":"App Theming Product","description":"Items that are related to the App level theming controls epic","color":"48883f"},"UI Building Product":{"color":"48883f","name":"UI Building Product","description":"Issues related to the UI Building experience"},"Onboarding Product":{"color":"48883f","name":"Onboarding Product","description":"Issues related to onboarding new developers"},"Database Schema":{"name":"Database Schema","description":"Issues related to database schema","color":"48883f"},"Git Product":{"color":"7e018f","name":"Git Product","description":"Issues related to version control product"},"Embedding Apps Product":{"name":"Embedding Apps Product","description":"Issues related to embedding","color":"48883f"},"Integrations Product":{"name":"Integrations Product","description":"Issues related to a specific integration","color":"b9f21c"},"Feature Flagging":{"name":"Feature Flagging","description":"Anything related feature flagging","color":"4574ae"},"Audit Logs Product":{"name":"Audit Logs Product","description":"Audit trails to ensure data security","color":"4574ae"},"Identity & Authentication Product":{"name":"Identity & Authentication Product","description":"Issues related to user identity & authentication","color":"4574ae"},"Email verification":{"name":"Email verification","description":"Email verification issues","color":"4574ae"},"Artifact Platform Product":{"name":"Artifact Platform Product","description":"Issues related to the application platform","color":"4574ae"},"Git IA":{"name":"Git IA","description":"Issues related to Git IA changes","color":"df8bd6"},"Documentation Pod":{"name":"Documentation Pod","description":"Issues related to user education","color":"8c8c02"},"Branch management":{"name":"Branch management","description":"Issues related to using a branch management on git","color":"ebe6af"},"Reconfigure Datasource Modal":{"name":"Reconfigure Datasource Modal","description":"Issues related to reconfigure DS modal that comes after importing applications","color":"5ac17b"},"Setup Issues":{"name":"Setup Issues","description":"Issues related to setting up appsmith","color":"3fc837"},"Packages & Git Pod":{"name":"Packages & Git Pod","description":"All issues belonging to Packages and Git","color":"46ac0e"},"Git Platform":{"name":"Git Platform","description":"Issues related to the git & the app platform","color":"c9ab80"},"Entity Management":{"name":"Entity Management","description":"Copy / Move / Delete widgets / queries / datasources","color":"74c33c"},"Cypress":{"name":"Cypress","description":"Tasks related to Cypress automation","color":"67b83c"},"Query & Widgets Pod":{"name":"Query & Widgets Pod","description":"All issues related to Query, JS, Eval, and Widgets","color":"94cade"},"Cloud Billing":{"name":"Cloud Billing","description":"Label to aggregate tickets related to multi-tenancy/cloud billing.","color":"138d87"}},"success":true} \ No newline at end of file +{"runners":[{"versioning":{"source":"milestones","type":"SemVer"},"prereleaseName":"alpha","issue":{"labels":{"Widgets Product":{"conditions":[{"label":"Button Widget","type":"hasLabel","value":true},{"label":"Chart 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":"New Widget","type":"hasLabel","value":true},{"label":"Switch widget","type":"hasLabel","value":true},{"label":"Audio Widget","type":"hasLabel","value":true},{"label":"Icon Button 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":"View Mode","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":"Button Group widget","type":"hasLabel","value":true},{"label":"Progress bar widget","type":"hasLabel","value":true},{"label":"Audio Recorder Widget","type":"hasLabel","value":true},{"label":"Camera Widget","type":"hasLabel","value":true},{"label":"Table Widget V2","type":"hasLabel","value":true},{"label":"Map Chart Widget","type":"hasLabel","value":true},{"label":"Code Scanner Widget","type":"hasLabel","value":true},{"label":"Widget keyboard accessibility","type":"hasLabel","value":true},{"label":"List Widget V2","type":"hasLabel","value":true},{"label":"Slider Widget","type":"hasLabel","value":true},{"label":"One-click Binding","type":"hasLabel","value":true},{"label":"Old widget version","type":"hasLabel","value":true},{"label":"Widget Discoverability","type":"hasLabel","value":true},{"label":"Switch Group Widget","type":"hasLabel","value":true},{"label":"Checkbox Group widget","type":"hasLabel","value":true},{"label":"Checkbox Widget","type":"hasLabel","value":true},{"label":"Table Inline Edit","type":"hasLabel","value":true},{"label":"Custom Widgets","type":"hasLabel","value":true}],"requires":1},"Javascript Product":{"conditions":[{"label":"JS Linting & Errors","type":"hasLabel","value":true},{"label":"Autocomplete","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 Usability","type":"hasLabel","value":true},{"label":"Framework Functions","type":"hasLabel","value":true},{"label":"JS Objects","type":"hasLabel","value":true},{"label":"JS Evaluation","type":"hasLabel","value":true},{"label":"Custom JS Libraries","type":"hasLabel","value":true},{"label":"Action Selector","type":"hasLabel","value":true},{"label":"Widget setter method","type":"hasLabel","value":true},{"label":"Entity Refactor","type":"hasLabel","value":true},{"label":"AST-frontend","type":"hasLabel","value":true},{"label":"Sniping Mode","type":"hasLabel","value":true},{"label":"AST-backend","type":"hasLabel","value":true}],"requires":1},"IDE Product":{"conditions":[{"label":"IDE Product","type":"hasLabel","value":true},{"label":"IDE Infra","type":"hasLabel","value":true},{"label":"IDE Navigation","type":"hasLabel","value":true},{"label":"IDE tabs","type":"hasLabel","value":true},{"label":"Omnibar","type":"hasLabel","value":true},{"label":"Entity Explorer","type":"hasLabel","value":true},{"label":"Page Management","type":"hasLabel","value":true},{"label":"Preview mode","type":"hasLabel","value":true},{"label":"Entity Management","type":"hasLabel","value":true}],"requires":1},"Accelerators Product":{"conditions":[{"label":"Generate Page","type":"hasLabel","value":true},{"label":"Building blocks","type":"hasLabel","value":true}],"requires":1},"Templates Product":{"conditions":[{"label":"Partial-import-export","type":"hasLabel","value":true},{"label":"Templates Product","type":"hasLabel","value":true}],"requires":1},"Design System Product":{"conditions":[{"label":"Design System Product","type":"hasLabel","value":true},{"label":"ADS Component Issue","type":"hasLabel","value":true},{"label":"Keyboard accessibility ","type":"hasLabel","value":true},{"label":"Toggle button","type":"hasLabel","value":true},{"label":"ADS Category Token","type":"hasLabel","value":true},{"label":"ADS Component Documentation","type":"hasLabel","value":true},{"label":"ADS Migration","type":"hasLabel","value":true},{"label":"ADS Deduplication ","type":"hasLabel","value":true},{"label":"ADS Revamp","type":"hasLabel","value":true},{"label":"ADS Deduplication","type":"hasLabel","value":true},{"label":"ADS Unit Test","type":"hasLabel","value":true},{"label":"ADS Components","type":"hasLabel","value":true},{"label":"ADS Grayscale","type":"hasLabel","value":true},{"label":"Design System","type":"hasLabel","value":true},{"label":"ADS Typography","type":"hasLabel","value":true},{"label":"ADS Visual Styles","type":"hasLabel","value":true},{"label":"ADS Component Design","type":"hasLabel","value":true},{"label":"Modal Component","type":"hasLabel","value":true},{"label":"ADS Spacing","type":"hasLabel","value":true},{"label":"ads unit test","type":"hasLabel","value":true},{"label":"ads revamp","type":"hasLabel","value":true},{"label":"ads deduplication","type":"hasLabel","value":true}],"requires":1},"RBAC Product":{"conditions":[{"label":"Invite users","type":"hasLabel","value":true},{"label":"RBAC Product","type":"hasLabel","value":true}],"requires":1},"Workspace Product":{"conditions":[{"label":"Home Page","type":"hasLabel","value":true},{"label":"Workspace Product","type":"hasLabel","value":true}],"requires":1},"Billing & Licensing Product":{"conditions":[{"label":"Customer Portal","type":"hasLabel","value":true},{"label":"Cloud Services","type":"hasLabel","value":true},{"label":"Billing","type":"hasLabel","value":true},{"label":"Self Serve","type":"hasLabel","value":true},{"label":"Enterprise Billing","type":"hasLabel","value":true},{"label":"Analytics Improvements","type":"hasLabel","value":true},{"label":"Self Serve 1.0","type":"hasLabel","value":true},{"label":"License","type":"hasLabel","value":true},{"label":"BE instance","type":"hasLabel","value":true},{"label":"Invite flow","type":"hasLabel","value":true},{"label":"CE Instance Usage","type":"hasLabel","value":true},{"label":"Feature Flagging","type":"hasLabel","value":true}],"requires":1},"Packages Product":{"conditions":[{"label":"Packages Product","type":"hasLabel","value":true}],"requires":1},"Environments Product":{"conditions":[{"label":"Environments Product","type":"hasLabel","value":true}],"requires":1},"UI Building Product":{"conditions":[{"label":"Property Pane","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":"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":"Canvas / Grid","type":"hasLabel","value":true},{"label":"Auto Height","type":"hasLabel","value":true},{"label":"Browser specific","type":"hasLabel","value":true},{"label":"Auto Layout","type":"hasLabel","value":true},{"label":"Fixed layout","type":"hasLabel","value":true},{"label":"App Navigation","type":"hasLabel","value":true}],"requires":1},"Onboarding Product":{"conditions":[{"label":"Welcome Screen","type":"hasLabel","value":true}],"requires":1},"Git Product":{"conditions":[{"label":"Git Product","type":"hasLabel","value":true},{"label":"Git Auto-commit","type":"hasLabel","value":true},{"label":"Auto-commit","type":"hasLabel","value":true},{"label":"Continuous Deployment","type":"hasLabel","value":true},{"label":"Default branch","type":"hasLabel","value":true},{"label":"Git status","type":"hasLabel","value":true},{"label":"Git performance","type":"hasLabel","value":true},{"label":"SDLC","type":"hasLabel","value":true},{"label":"Git IA","type":"hasLabel","value":true},{"label":"Branch management","type":"hasLabel","value":true}],"requires":1},"Embedding Apps Product":{"conditions":[{"label":"Embedding Apps Product","type":"hasLabel","value":true}],"requires":1},"Integrations Product":{"conditions":[{"label":"New Datasource","type":"hasLabel","value":true},{"label":"Firestore","type":"hasLabel","value":true},{"label":"Google Sheets","type":"hasLabel","value":true},{"label":"Mongo","type":"hasLabel","value":true},{"label":"Redshift","type":"hasLabel","value":true},{"label":"snowflake","type":"hasLabel","value":true},{"label":"S3","type":"hasLabel","value":true},{"label":"Redis","type":"hasLabel","value":true},{"label":"Postgres","type":"hasLabel","value":true},{"label":"GraphQL Plugin","type":"hasLabel","value":true},{"label":"ArangoDB","type":"hasLabel","value":true},{"label":"MsSQL","type":"hasLabel","value":true},{"label":"Elastic Search","type":"hasLabel","value":true},{"label":"OAuth","type":"hasLabel","value":true},{"label":"Airtable","type":"hasLabel","value":true},{"label":"CURL","type":"hasLabel","value":true},{"label":"DynamoDB","type":"hasLabel","value":true},{"label":"Zendesk","type":"hasLabel","value":true},{"label":"Hubspot","type":"hasLabel","value":true},{"label":"Query Forms","type":"hasLabel","value":true},{"label":"Twilio","type":"hasLabel","value":true},{"label":"MySQL","type":"hasLabel","value":true},{"label":"Connection pool","type":"hasLabel","value":true},{"label":"MariaDB","type":"hasLabel","value":true},{"label":"Integrations Pod General","type":"hasLabel","value":true},{"label":"SMTP plugin","type":"hasLabel","value":true},{"label":"Oracle SQL DB","type":"hasLabel","value":true},{"label":"Query filter","type":"hasLabel","value":true},{"label":"Activation - datasources","type":"hasLabel","value":true},{"label":"REST API","type":"hasLabel","value":true},{"label":"REST API","type":"hasLabel","value":true},{"label":"Datasources","type":"hasLabel","value":true},{"label":"REST API plugin","type":"hasLabel","value":true},{"label":"Prepared statements","type":"hasLabel","value":true},{"label":"Query Generation","type":"hasLabel","value":true},{"label":"Core Query Execution","type":"hasLabel","value":true},{"label":"Query Management","type":"hasLabel","value":true},{"label":"Query Settings","type":"hasLabel","value":true},{"label":"Query performance","type":"hasLabel","value":true},{"label":"Datatype issue","type":"hasLabel","value":true},{"label":"SmartSubstitution","type":"hasLabel","value":true},{"label":"Suggested Widgets","type":"hasLabel","value":true},{"label":"SAAS Plugins","type":"hasLabel","value":true},{"label":"Reconnect DS modal","type":"hasLabel","value":true},{"label":"OnPageLoad","type":"hasLabel","value":true},{"label":"File upload issues","type":"hasLabel","value":true},{"label":"AI","type":"hasLabel","value":true},{"label":"Appsmith AI","type":"hasLabel","value":true},{"label":"Database Schema","type":"hasLabel","value":true},{"label":"AWS Lambda","type":"hasLabel","value":true}],"requires":1},"Identity & Authentication Product":{"conditions":[{"label":"Login / Signup","type":"hasLabel","value":true},{"label":"SSO","type":"hasLabel","value":true},{"label":"SCIM","type":"hasLabel","value":true},{"label":"Email verification","type":"hasLabel","value":true}],"requires":1},"Artifact Platform Product":{"conditions":[{"label":"Fork App","type":"hasLabel","value":true},{"label":"Publish App","type":"hasLabel","value":true},{"label":"Secret Management","type":"hasLabel","value":true},{"label":"Import-Export-App","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},{"label":"Backup & Restore","type":"hasLabel","value":true},{"label":"AWS AMI","type":"hasLabel","value":true},{"label":"Observability","type":"hasLabel","value":true},{"label":"Heroku","type":"hasLabel","value":true},{"label":"New Deployment Mode","type":"hasLabel","value":true},{"label":"Supervisor","type":"hasLabel","value":true},{"label":"Deployment Certificates","type":"hasLabel","value":true},{"label":"Mock Data","type":"hasLabel","value":true},{"label":"AWS ECS","type":"hasLabel","value":true},{"label":"Ingress","type":"hasLabel","value":true},{"label":"Nginx","type":"hasLabel","value":true},{"label":"Setup Issues","type":"hasLabel","value":true}],"requires":1},"Performance Pod":{"conditions":[{"label":"Performance","type":"hasLabel","value":true},{"label":"Performance infra","type":"hasLabel","value":true}],"requires":1},"IDE Pod":{"conditions":[{"label":"Telemetry","type":"hasLabel","value":true},{"label":"i18n","type":"hasLabel","value":true},{"label":"IDE Product","type":"hasLabel","value":true},{"label":"App setting","type":"hasLabel","value":true},{"label":"Debugger Product","type":"hasLabel","value":true},{"label":"Embedding Apps Product","type":"hasLabel","value":true}],"requires":1},"Platform Administration Pod":{"conditions":[{"label":"Airgap","type":"hasLabel","value":true},{"label":"Enterprise Edition","type":"hasLabel","value":true},{"label":"Invite flow","type":"hasLabel","value":true},{"label":"User Profile","type":"hasLabel","value":true},{"label":"User Session ","type":"hasLabel","value":true},{"label":"User Session","type":"hasLabel","value":true},{"label":"Admin Settings Product","type":"hasLabel","value":true},{"label":"RBAC Product","type":"hasLabel","value":true},{"label":"Workspace Product","type":"hasLabel","value":true},{"label":"Branding Product","type":"hasLabel","value":true},{"label":"Audit Logs Product","type":"hasLabel","value":true},{"label":"Identity & Authentication Product","type":"hasLabel","value":true},{"label":"Billing & Licensing Product","type":"hasLabel","value":true},{"label":"Move to Postgres","type":"hasLabel","value":true},{"label":"Cloud Billing","type":"hasLabel","value":true}],"requires":1},"DB Infrastructure Pod":{"conditions":[],"requires":1},"Packages Pod":{"conditions":[{"label":"Module creator","type":"hasLabel","value":true},{"label":"Module consumer","type":"hasLabel","value":true},{"label":"Package versioning","type":"hasLabel","value":true},{"label":"Convert to module","type":"hasLabel","value":true},{"label":"Query module","type":"hasLabel","value":true},{"label":"JS module","type":"hasLabel","value":true},{"label":"UI module","type":"hasLabel","value":true},{"label":"Packages Pod","type":"hasLabel","value":true}],"requires":1},"Workflows Pod":{"conditions":[{"label":"Workflows Product","type":"hasLabel","value":true}],"requires":1},"Query & JS Pod":{"conditions":[{"label":"Javascript Product","type":"hasLabel","value":true},{"label":"Onboarding Product","type":"hasLabel","value":true},{"label":"Integrations Product","type":"hasLabel","value":true},{"label":"Reconfigure Datasource Modal","type":"hasLabel","value":true}],"requires":1},"QA Pod":{"conditions":[{"label":"Automation Test","type":"hasLabel","value":true},{"label":"TestGap","type":"hasLabel","value":true},{"label":"Automation failures","type":"hasLabel","value":true},{"label":"Needs automation","type":"hasLabel","value":true},{"label":"cypress-flaky-fix","type":"hasLabel","value":true},{"label":"Cypress flaky tests","type":"hasLabel","value":true},{"label":"Cypress","type":"hasLabel","value":true}],"requires":1},"Anvil POD":{"conditions":[{"label":"Checkbox Component","type":"hasLabel","value":true},{"label":"WDS team","type":"hasLabel","value":true},{"label":"Anvil POD","type":"hasLabel","value":true},{"label":"WDS - all widgets","type":"hasLabel","value":true},{"label":"WDS - input widget","type":"hasLabel","value":true},{"label":"WDS - paragraph widget","type":"hasLabel","value":true},{"label":"WDS - statbox widget","type":"hasLabel","value":true},{"label":"WDS - modal widget","type":"hasLabel","value":true},{"label":"WDS - icon widget","type":"hasLabel","value":true},{"label":"WDS - checkbox widget","type":"hasLabel","value":true},{"label":"WDS - table widget","type":"hasLabel","value":true},{"label":"WDS - keyValue widget","type":"hasLabel","value":true},{"label":"WDS - switch group widget","type":"hasLabel","value":true},{"label":"WDS - theming","type":"hasLabel","value":true},{"label":"Anvil layout","type":"hasLabel","value":true},{"label":"Anvil - theming","type":"hasLabel","value":true},{"label":"Anvil - vertical alignment","type":"hasLabel","value":true},{"label":"Anvil - layout component","type":"hasLabel","value":true},{"label":"Anvil - drag & drop","type":"hasLabel","value":true},{"label":"Anvil - zones & sections","type":"hasLabel","value":true},{"label":"Anvil - copy paste experience","type":"hasLabel","value":true},{"label":"WDS - phone widget","type":"hasLabel","value":true},{"label":"WDS - responsive widget","type":"hasLabel","value":true},{"label":"Anvil - responsive viewport","type":"hasLabel","value":true},{"label":"WDS - widget styling","type":"hasLabel","value":true},{"label":"Anvil - spacing","type":"hasLabel","value":true},{"label":"Anvil - responsive canvas","type":"hasLabel","value":true},{"label":"WDS - inline button widget","type":"hasLabel","value":true},{"label":"Anvil team","type":"hasLabel","value":true}],"requires":1},"Activation Pod":{"conditions":[{"label":"Activation","type":"hasLabel","value":true}],"requires":1},"Stability Pod":{"conditions":[{"label":"Stability Issue","type":"hasLabel","value":true}],"requires":1},"Documentation Pod":{"conditions":[{"label":"Documentation","type":"hasLabel","value":true}],"requires":1},"Packages & Git Pod":{"conditions":[{"label":"Packages Pod","type":"hasLabel","value":true},{"label":"Git Product","type":"hasLabel","value":true},{"label":"Packages Product","type":"hasLabel","value":true},{"label":"Git Platform","type":"hasLabel","value":true}],"requires":1},"Git Platform":{"conditions":[{"label":"Environments Product","type":"hasLabel","value":true},{"label":"Artifact Platform Product","type":"hasLabel","value":true}],"requires":1},"Query & Widgets Pod":{"conditions":[{"label":"Query & JS Pod","type":"hasLabel","value":true},{"label":"Widgets & Accelerators Pod","type":"hasLabel","value":true}],"requires":1},"Widgets & Accelerators Pod":{"conditions":[{"label":"Accelerators Product","type":"hasLabel","value":true},{"label":"Templates Product","type":"hasLabel","value":true},{"label":"App Theming Product","type":"hasLabel","value":true},{"label":"Widgets Product","type":"hasLabel","value":true}],"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"},"Checkbox Group widget":{"color":"bbeecd","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":"748fda","name":"QA","description":"Needs QA attention"},"Verified":{"color":"9bf416","name":"Verified","description":""},"Wont Fix":{"color":"ffffff","name":"Wont Fix","description":"This will not be worked on"},"MySQL":{"color":"c9ddc6","name":"MySQL","description":"Issues related to MySQL plugin"},"Development":{"color":"9F8A02","name":"Development","description":""},"Help Wanted":{"color":"008672","name":"Help Wanted","description":"Extra attention is needed"},"Home Page":{"color":"","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"},"Fork App":{"color":"af87c7","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":""},"Needs Design":{"color":"bfd4f2","name":"Needs Design","description":"needs design or changes to design"},"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":""},"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":"8078b0","name":"Firestore","description":"Issues related to the firestore Integration"},"New Widget":{"color":"be4cf2","name":"New Widget","description":"A request for a new widget"},"Modal Widget":{"color":"03846f","name":"Modal Widget","description":""},"UX Improvement":{"color":"f4a089","name":"UX Improvement","description":""},"S3":{"color":"8078b0","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"},"Calendar Widget":{"color":"8c6644","name":"Calendar Widget","description":""},"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"},"Checkbox Widget":{"color":"bbeecd","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":"8ba6fd","name":"Bug","description":"Something isn't right"},"Widget Validation":{"color":"6990BC","name":"Widget Validation","description":"Issues related to widget property validation"},"Generate Page":{"color":"2b4664","name":"Generate Page","description":"Issures related to page generation"},"File Picker Widget":{"color":"6ae4f2","name":"File Picker Widget","description":""},"snowflake":{"color":"8078b0","name":"snowflake","description":"Issues related to the snowflake Integration"},"Automation":{"color":"CCAF60","name":"Automation","description":""},"hotfix":{"color":"BA3F1D","name":"hotfix","description":""},"Import-Export-App":{"color":"48883f","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"},"Telemetry":{"color":"bc70f9","name":"Telemetry","description":"Issues related to instrumenting appsmith"},"Radio Widget":{"color":"91ef15","name":"Radio Widget","description":""},"Omnibar":{"color":"1bb96a","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":""},"Task":{"color":"085630","name":"Task","description":"A simple Todo"},"Design System":{"color":"2958a4","name":"Design System","description":"Design system"},"opera":{"color":"C63F5B","name":"opera","description":"Any issues identified on the opera browser"},"Login / Signup":{"color":"","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"},"Production":{"color":"b60205","name":"Production","description":""},"Dependencies":{"color":"0366d6","name":"Dependencies","description":"Pull requests that update a dependency file"},"Google Sheets":{"color":"8078b0","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":"8078b0","name":"Mongo","description":"Issues related to Mongo DB plugin"},"Documentation":{"color":"a8dff7","name":"Documentation","description":"Improvements or additions to documentation"},"TestGap":{"color":"","name":"TestGap","description":"Issues identified for test plan improvement"},"keyboard shortcut":{"color":"0688B6","name":"keyboard shortcut","description":""},"Reopen":{"color":"897548","name":"Reopen","description":""},"Redshift":{"color":"8078b0","name":"Redshift","description":"Issues related to the redshift integration"},"Date Picker Widget":{"color":"ef1ce1","name":"Date Picker Widget","description":""},"Entity Explorer":{"color":"1bb96a","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},"Text Widget":{"color":"d130d1","name":"Text Widget","description":""},"Video Widget":{"color":"23dd4b","name":"Video Widget","description":""},"Datasources":{"color":"3d590f","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"},"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"},"UI Performance":{"color":"1799b0","name":"UI Performance","description":"Issues related to UI performance"},"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"},"Chart Widget":{"color":"616ecc","name":"Chart Widget","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"},"Sniping Mode":{"name":"Sniping Mode","description":"Issues related to sniping mode","color":"48883f"},"Redis":{"name":"Redis","description":"Issues related to Redis","color":"8078b0"},"New Datasource":{"color":"60b14c","name":"New Datasource","description":"Requests for new datasources"},"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":"4773ab"},"Widgets Pane":{"name":"Widgets Pane","description":"Issues related to the discovery and organisation of widgets","color":"ad5d78"},"View Mode":{"color":"1799b0","name":"View Mode","description":"Issues related to the view mode"},"Content":{"name":"Content","description":"For content related topics i.e blogs, templates, videos","color":"a8dff7"},"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":"8078b0"},"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":"e6038e"},"SAAS Plugins":{"name":"SAAS Plugins","description":"Issues related to SAAS Plugins","color":"80e18f"},"JS Promises":{"name":"JS Promises","description":"Issues related to promises","color":"d7771f"},"OnPageLoad":{"name":"OnPageLoad","description":"OnPageLoad issues on functions and queries","color":"2b4664"},"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":"48883f"},"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"},"Reflow & Resize":{"name":"Reflow & Resize","description":"All issues related to reflow and resize experience","color":"748a13"},"SSO":{"name":"SSO","description":"Issues, requests and enhancements around Single sign-on.","color":""},"Multi User Realtime":{"name":"Multi User Realtime","description":"Issues related to multiple users using or editing an application","color":"e7b6ce"},"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":"8078b0"},"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":"8078b0"},"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":"60885f"},"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":"60885f"},"Canvas Zooms":{"name":"Canvas Zooms","description":"Issues related to zooming the canvas","color":"e6038e"},"business":{"name":"business","description":"Features that will be a part of our business edition","color":"cd59eb"},"Action Pod":{"name":"Action Pod","description":"","color":"ee2e36"},"AutomationGap1":{"color":"a5e07c","name":"AutomationGap1","description":"Issues that needs automated tests"},"A-Force11":{"name":"A-Force11","description":"Issues raised by A-Force team","color":"d667b6"},"Business Edition":{"name":"Business Edition","description":"Features that will be a part of our business edition","color":"89bb6c"},"storeValue":{"name":"storeValue","description":"Issues related to the store value function","color":"5d3e66"},"DynamoDB":{"name":"DynamoDB","description":"Issues that are related to DynamoDB should have this label","color":"60885f"},"Backup & Restore":{"name":"Backup & Restore","description":"Issues related to backup and restore","color":"86874d"},"Billing":{"name":"Billing","description":"Billing infrastructure and flows for Business Edition and Trial users","color":"d2bc40"},"Datatype issue":{"name":"Datatype issue","description":"Issues that have risen because data types weren't handled","color":"cef66b"},"OAuth":{"name":"OAuth","description":"OAuth related bugs or features","color":"60885f"},"Table Widget V2":{"name":"Table Widget V2","description":"Issues related to Table Widget V2","color":"3a7192"},"IDE Navigation":{"name":"IDE Navigation","description":"Issues/feature requests related to IDE navigation, and context switching","color":"1bb96a"},"Query performance":{"name":"Query performance","description":"Issues that have to do with lack in performance of query execution","color":"cef66b"},"SAAS Manager App":{"name":"SAAS Manager App","description":"Issues with the SAAS manager app","color":"d427db"},"Twilio":{"name":"Twilio","description":"Issues related to Twilio integration","color":"23ba8d"},"Hubspot":{"name":"Hubspot","description":"Issues related to Hubspot integration","color":"60885f"},"Zendesk":{"name":"Zendesk","description":"Issues related to Zendesk integration","color":"60885f"},"Entity Refactor":{"name":"Entity Refactor","description":"Issues related to refactor logic","color":"705a2c"},"Map Chart Widget":{"name":"Map Chart Widget","description":"Issues related to Map Chart Widgets","color":"c8397f"},"Product Catchup":{"name":"Product Catchup","description":"Issues created in the product catchup","color":"29cd2c"},"Framework Functions":{"name":"Framework Functions","description":"Issues related to internal functions like showAlert(), navigateTo() etc...","color":"c25a09"},"Frontend Libraries Upgrade":{"name":"Frontend Libraries Upgrade","description":"Issues related to frontend libraries upgrade","color":"ede1fc"},"MsSQL":{"name":"MsSQL","description":"Issues related to MsSQL plugin","color":"8078b0"},"Elastic Search":{"name":"Elastic Search","description":"Issues related to the elastic search datasource","color":"8078b0"},"Core Query Execution":{"color":"cef66b","name":"Core Query Execution","description":"Issues related to the execution of all queries"},"Query Management":{"name":"Query Management","description":"Issues related to the CRUD of actions or queries","color":"cef66b"},"Query Settings":{"name":"Query Settings","description":"Issues related to the settings of all queries","color":"cef66b"},"Code Editor":{"name":"Code Editor","description":"Issues related to the code editor","color":"4ca16e"},"Query Forms":{"color":"12b253","name":"Query Forms","description":"Isuses related to the query forms"},"JS Objects":{"color":"22962c","name":"JS Objects","description":"Issues related to JS Objects"},"JS Evaluation":{"color":"22962c","name":"JS Evaluation","description":"Issues related to JS evaluation on the platform"},"SmartSubstitution":{"name":"SmartSubstitution","description":"Issues related to Smart substitution of mustache bindings in queries","color":"bae511"},"Query Generation":{"name":"Query Generation","description":"Issues related to query generation","color":"cef66b"},"Suggested Widgets":{"name":"Suggested Widgets","description":"Issues related to suggesting widgets based on query response","color":"6ac063"},"Code Scanner Widget":{"name":"Code Scanner Widget","description":"Issues related to code scanner widget","color":"9bc1a0"},"Clean URLs":{"name":"Clean URLs","description":"Issues related to clean URLs epic","color":"112623"},"Widget keyboard accessibility":{"name":"Widget keyboard accessibility","description":"All issues related to keyboard accessibility in widgets","color":"b626fd"},"Connection pool":{"name":"Connection pool","description":"issues to do with connection pooling of various plugins","color":"94fe36"},"List Widget V2":{"name":"List Widget V2","description":"Issues related to the list widget v2","color":"adaaf7"},"Auto Height":{"name":"Auto Height","description":"Issues related to dynamic height of widgets","color":"5149cf"},"cypress_failed_test":{"name":"cypress_failed_test","description":"Cypress failed tests","color":"4745d5"},"Needs validation":{"name":"Needs validation","description":"Needs problem validation before being picked up","color":"66673d"},"Slider Widget":{"name":"Slider Widget","description":"Issues raised for slider widgets.","color":"2eef5f"},"Multitenancy":{"name":"Multitenancy","description":"Support multitenancy within single appsmith instance","color":"8c49a9"},"Conversion Algorithm":{"name":"Conversion Algorithm","description":"All issue related to converting app from fixed to flex mode & vice versa","color":"d12d2e"},"Browser specific":{"name":"Browser specific","description":"All issue related to browser","color":"d12d2e"},"Performance infra":{"name":"Performance infra","description":"all issue related to the performance infra","color":"8a60f6"},"DSL Update":{"name":"DSL Update","description":"Issues related to storing and updating the DSL","color":"e16cf3"},"AST-frontend":{"name":"AST-frontend","description":"Issues related to maintaining AST logic","color":"2b4664"},"AST-backend":{"name":"AST-backend","description":"Backend issues related to AST parsing","color":"48883f"},"MariaDB":{"name":"MariaDB","description":"MariaDB datasource","color":"8428c3"},"ADS Component Issue":{"name":"ADS Component Issue","description":"Issues which are caused due to ADS components","color":"d89119"},"Regressed":{"color":"723fd0","name":"Regressed","description":"Scenarios that were working before but have now regressed"},"Needs RCA":{"name":"Needs RCA","description":"a critical or high priority issue that needs an RCA","color":"2cc68f"},"Custom JS Libraries":{"name":"Custom JS Libraries","description":"Issues related to adding custom JS library","color":"bacb6d"},"Integrations Pod General":{"name":"Integrations Pod General","description":"Issues related to the Integrations Pod that don't fit into other tags.","color":"287823"},"Performance Pod":{"name":"Performance Pod","description":"All things related to Appsmith performance","color":"b5a25d"},"Performance":{"name":"Performance","description":"Issues related to performance","color":"9a18d7"},"File upload issues":{"name":"File upload issues","description":"Issues related to uploading any type of files from within Appsmith","color":"2b4664"},"Action Selector":{"name":"Action Selector","description":"Issues related to action selector on the property pane","color":"2f9e20"},"Community Reported":{"name":"Community Reported","description":"issues reported by community members","color":"1402e5"},"JS Function execution":{"name":"JS Function execution","description":"JS function execution","color":"7c2de1"},"Self Serve":{"name":"Self Serve","description":"For all issues related to self-serve flow for business edition","color":"4dacfc"},"Self Serve 1.0":{"name":"Self Serve 1.0","description":"For all issues related to v1 of the self serve project","color":"ae839e"},"Customer Portal":{"name":"Customer Portal","description":"For all tasks/issues pertaining to customer.appsmith.com","color":"d2bc40"},"Cloud Services":{"name":"Cloud Services","description":"For all tasks/issues on Appsmith cloud-services relating to licensing, usage and billing","color":"d2bc40"},"One-click Binding":{"name":"One-click Binding","description":"Issues related to the One click binding epic","color":"f1661c"},"Airgap":{"name":"Airgap","description":"Tickets related to supporting air-gapped Appsmith instances","color":"1cb294"},"SMTP plugin":{"name":"SMTP plugin","description":"Issues related to SMTP plugin","color":"541457"},"AWS AMI":{"name":"AWS AMI","description":"Issues Related to AWS AMI","color":"b44680"},"Old widget version":{"name":"Old widget version","description":"Use this label to raise issue specific only to an older version of a widget","color":"ff3814"},"Enterprise Billing":{"name":"Enterprise Billing","description":"To track all tasks/issues related to licensing & billing for enterprise customers","color":"14c156"},"Oracle SQL DB":{"name":"Oracle SQL DB","description":"Issues related to the Oracle plugin","color":"cbabcb"},"Community Contributor":{"name":"Community Contributor","description":"Meant to track issues that are assigned to external contributors","color":"149ab6"},"widget vertical alignment":{"name":"widget vertical alignment","description":"All issue related widget vertical alignment on the auto layout canvas","color":"d12d2e"},"Observability":{"name":"Observability","description":"Issues related to observability on the Appsmith instance","color":"dff913"},"Checkbox Component":{"name":"Checkbox Component","description":"This labels deals with checkbox component in wds package","color":"75a401"},"Analytics Improvements":{"name":"Analytics Improvements","description":"For all tasks focused on improving our overall analytics and fixing any issues ","color":"29b8ed"},"WDS team":{"name":"WDS team","description":"","color":"8d675a"},"Enterprise Edition":{"name":"Enterprise Edition","description":"Features that will be supported in Enterprise Edition only","color":"984f5e"},"Query filter":{"name":"Query filter","description":"Issues related to query filtering, e.g., WHERE clause","color":"a15134"},"Keyboard accessibility ":{"name":"Keyboard accessibility ","description":"All issue related to ADS component keyboard accessibility","color":"2ba696"},"Toggle button":{"name":"Toggle button","description":"All issue related to ADS toggle button","color":"edc47f"},"SCIM":{"name":"SCIM","description":"Label to collate our SCIM issues","color":"48883f"},"ADS Category Token":{"name":"ADS Category Token","description":"All issues related appsmith design system category tokens","color":"920961"},"ADS Component Documentation":{"name":"ADS Component Documentation","description":"All issues Appsmith design system component documentation","color":"64c46a"},"ADS Migration":{"name":"ADS Migration","description":"All issues related to Appsmith design system migration","color":"b082d6"},"ADS Deduplication ":{"name":"ADS Deduplication ","description":"Replacing component with ADS components","color":"b082d6"},"ADS Revamp":{"name":"ADS Revamp","description":"All issues related to ads revamp. ","color":"b082d6"},"ADS Deduplication":{"name":"ADS Deduplication","description":"Replacing component with ADS components","color":"b082d6"},"ADS Grayscale":{"name":"ADS Grayscale","description":"Support grayscale color changes","color":"b03577"},"ADS Unit Test":{"name":"ADS Unit Test","description":"All issue related ads unit cases ","color":"b082d6"},"ADS Components":{"name":"ADS Components","description":"All issues related ADS components","color":"b082d6"},"Widget Discoverability":{"name":"Widget Discoverability","description":"Issues related to Widget Discoverability","color":"7b55ce"},"Widget setter method":{"name":"Widget setter method","description":"Issues with widget property setters","color":"8dce87"},"License":{"name":"License","description":"For all issues/tasks related to licensing of appsmith-ee edition","color":"90ee98"},"Platformization":{"name":"Platformization","description":"Issues or tasks related to platformization of Appsmith codebase","color":"4e972b"},"Activation - datasources":{"name":"Activation - datasources","description":"issues related to activation projects","color":"7c7ace"},"Partial-import-export":{"name":"Partial-import-export","description":"Label for granular reusability.","color":"717732"},"AI":{"name":"AI","description":"All tasks related to AI","color":"2b4664"},"ADS Typography":{"name":"ADS Typography","description":"All issue related typographical changes","color":"2dbe8d"},"Auto Layout":{"name":"Auto Layout","description":"Issues relates to auto layout","color":"92cf8c"},"Heroku":{"name":"Heroku","description":"Issues related to Heroku","color":"a81b69"},"ADS Visual Styles":{"name":"ADS Visual Styles","description":"All issues related to ADS visual styles","color":"d3da89"},"ADS Component Design":{"name":"ADS Component Design","description":"All issue related to component design","color":"5cc91e"},"Modal Component":{"name":"Modal Component","description":"All issue related to ads modal component","color":"ee63f3"},"App setting":{"name":"App setting","description":"Related to app settings panel within the app","color":"174f98"},"BE instance":{"name":"BE instance","description":"For all issues related to license, billing on BE instance","color":"ae8f98"},"Fixed layout":{"name":"Fixed layout","description":"issues related to fixed layout","color":"b66681"},"Anvil layout":{"name":"Anvil layout","description":"issues related to the new layout system anvil","color":"5e0904"},"New Deployment Mode":{"name":"New Deployment Mode","description":"Support a new mode of deployment","color":"108033"},"Custom widgets":{"name":"Custom widgets","description":"For all issues related to the custom widget project","color":"c9db9c"},"Homepage Experience V2":{"name":"Homepage Experience V2","description":"Label for reporting new tasks and bug fixes related to revamped homepage experience","color":"c55d54"},"Customer Success":{"name":"Customer Success","description":"Issues that the success team cares about","color":"6ccabd"},"Invite flow":{"name":"Invite flow","description":"Invite users flow and any associated actions","color":"881b35"},"Invite users":{"name":"Invite users","description":"Invite users flow and any associated actions","color":""},"Workflows Pod":{"name":"Workflows Pod","description":"Issues that the workflows team owns","color":"446925"},"DailyPromotionBlocker":{"name":"DailyPromotionBlocker","description":"DailyPromotion Blocker","color":"9b2280"},"JS Binding":{"name":"JS Binding","description":"All issues related to the JS Binding experience","color":"422fed"},"REST API":{"name":"REST API","description":"REST API plugin related issues","color":"e3ede5"},"Critical":{"color":"a1e3db","name":"Critical","description":"This issue breaks existing apps. Drop everything else to resolve"},"Module creator":{"name":"Module creator","description":"Issues related to the module creator side","color":"bb2c05"},"Module consumer":{"name":"Module consumer","description":"Issues related to the module consumer side","color":"83d3c5"},"Package versioning":{"name":"Package versioning","description":"ISsues related to how we manage versions for packages","color":"4c5218"},"Convert to module":{"name":"Convert to module","description":"Issues related to the module creation flow using conversion","color":"4c5218"},"Query module":{"name":"Query module","description":"Issues affecting query modules or its instances","color":"b11a7e"},"JS module":{"name":"JS module","description":"Issues affecting JS modules or its instances","color":"bf76f6"},"Secret Management":{"name":"Secret Management","description":"Issues related to secret management","color":"2b4664"},"REST API plugin":{"name":"REST API plugin","description":"REST API plugin related issues","color":"b5948a"},"UI module":{"name":"UI module","description":"Issues affecting UI modules or its instances","color":"d2acee"},"Preview mode":{"name":"Preview mode","description":"Issues related to app previews","color":"48883f"},"Git Auto-commit":{"name":"Git Auto-commit","description":"Issues related to autocommit","color":"717732"},"QA Pod":{"name":"QA Pod","description":"Issues under the QA Pod","color":"717732"},"Automation Test":{"name":"Automation Test","description":"","color":""},"Automation failures":{"name":"Automation failures","description":"","color":""},"Needs automation":{"name":"Needs automation","description":"Issues that needs automated tests","color":""},"Prepared statements":{"name":"Prepared statements","description":"Issues related to prepared statement flow","color":""},"Switch Group Widget":{"name":"Switch Group Widget","description":"Issues related to Switch group Widget","color":""},"Supervisor":{"name":"Supervisor","description":"Issues related to supervisor","color":"2c5813"},"Deployment Certificates":{"name":"Deployment Certificates","description":"Issues related to lets encrypt","color":"e148aa"},"Mock Data":{"name":"Mock Data","description":"Issues related to mock databases","color":"ebf251"},"AWS ECS":{"name":"AWS ECS","description":"Issues related to ECS Fargate","color":"e506ff"},"Publish App":{"name":"Publish App","description":"Issues related to app deployment","color":"2b4664"},"IDE Infra":{"name":"IDE Infra","description":"Issues related to the IDE infrastructure like saving changes","color":"1bb96a"},"User Profile":{"name":"User Profile","description":"Issues related to a user profile","color":"a60d34"},"Page Management":{"color":"1bb96a","name":"Page Management","description":"Issues related to configuring pages"},"Ingress":{"name":"Ingress","description":"Ingress Controller","color":"a86802"},"Nginx":{"name":"Nginx","description":"Issues related to Nginx","color":"e54195"},"Building blocks":{"name":"Building blocks","description":"Building blocks on cavas, on templates listing or drag and drop of building blocks.","color":"48883f"},"Table Inline Edit":{"name":"Table Inline Edit","description":"Issues related to inline editing","color":"60895a"},"User Session ":{"name":"User Session ","description":"For all issues/tasks related to user sessions","color":"65a3f5"},"WDS - all widgets":{"name":"WDS - all widgets","description":"all widget present in WDS","color":"2670ae"},"WDS - input widget":{"name":"WDS - input widget","description":"Issues related to input widget on WDS","color":"2670ae"},"WDS - paragraph widget":{"name":"WDS - paragraph widget","description":"issues related to paragraph widget on WDS","color":"2670ae"},"WDS - statbox widget":{"name":"WDS - statbox widget","description":"issues related to statbox widget on WDS","color":"2670ae"},"WDS - modal widget":{"name":"WDS - modal widget","description":"Issues related to modal widget on WDS","color":"2670ae"},"WDS - icon widget":{"name":"WDS - icon widget","description":"Issues related to icon widget on WDS","color":"2670ae"},"WDS - checkbox widget":{"name":"WDS - checkbox widget","description":"Issues related to checkbox widget on WDS","color":"2670ae"},"WDS - table widget":{"name":"WDS - table widget","description":"Issues related to table widget on WDS","color":"2670ae"},"WDS - keyValue widget":{"name":"WDS - keyValue widget","description":"Issues related to key-value widget on WDS","color":"2670ae"},"WDS - switch group widget":{"name":"WDS - switch group widget","description":"Issues related to switch group widget on WDS","color":"2670ae"},"WDS - theming":{"name":"WDS - theming","description":"Issues related to theming on the Anvil instance","color":"2670ae"},"Anvil POD":{"name":"Anvil POD","description":"Issue related to Anvil project","color":"5e0904"},"Anvil - theming":{"name":"Anvil - theming","description":"Issues related to theming on the Anvil instance","color":"c28de5"},"Anvil - vertical alignment":{"name":"Anvil - vertical alignment","description":"Issues related to vertical alignment on the Anvil layout","color":"c28de5"},"Anvil - layout component":{"name":"Anvil - layout component","description":"Issues related to layout component on the Anvil layout","color":"c28de5"},"Anvil - drag & drop":{"name":"Anvil - drag & drop","description":"Issues related to drag & drop experience on Anvil","color":"c28de5"},"Anvil - zones & sections":{"name":"Anvil - zones & sections","description":"Issues related to zones and sections on the Anvil layout","color":"c28de5"},"Anvil - copy paste experience":{"name":"Anvil - copy paste experience","description":"Issues related to copy paste experience on the Anvil layout","color":"c28de5"},"WDS - phone widget":{"name":"WDS - phone widget","description":"Issues related to phone widget on WDS","color":"c28de5"},"WDS - responsive widget":{"name":"WDS - responsive widget","description":"All issues related to widget responsiveness","color":"11ee05"},"Anvil - responsive viewport":{"color":"11ee05","name":"Anvil - responsive viewport","description":"Issues seen on different viewports like mobile"},"WDS - widget styling":{"color":"11ee05","name":"WDS - widget styling","description":"all about widget styling"},"Anvil - spacing":{"name":"Anvil - spacing","description":"Related to spacing between widgets in auto layout","color":"11ee05"},"Anvil - responsive canvas":{"name":"Anvil - responsive canvas","description":"All issues related to canvas responsiveness","color":"11ee05"},"WDS - inline button widget":{"name":"WDS - inline button widget","description":"Issues related to inline button widget on WDS","color":"7cef83"},"Activation Pod":{"name":"Activation Pod","description":"for Activation group","color":"d67d00"},"Activation":{"name":"Activation","description":"for Activation group","color":"d67d00"},"Tests":{"name":"Tests","description":"Test issues","color":"4fc7b6"},"Ballpark: XXS":{"name":"Ballpark: XXS","description":"~1xDev in 1/2xSprint","color":""},"Ballpark: XS":{"name":"Ballpark: XS","description":"~1xDev in 1xSprint","color":"53bf71"},"Ballpark: S":{"name":"Ballpark: S","description":"~2xDev in 1xSprint","color":"6e9e65"},"Ballpark: M":{"name":"Ballpark: M","description":"~1xPOD in 1xSprint","color":"2229e6"},"Ballpark: L":{"name":"Ballpark: L","description":"~1xPOD in 3xSprint or 2xPODs in 1xSprint","color":"49962f"},"Ballpark: XL":{"name":"Ballpark: XL","description":"~1xPOD in 1xQuarter or 2xPODs in 2xSprint","color":"b524c9"},"Ballpark: XXL":{"name":"Ballpark: XXL","description":"~2xPODs in 1xQuarter","color":"22092c"},"Auto-commit":{"name":"Auto-commit","description":"Issues related to auto-generated commits showing up on git ","color":"e25b89"},"Continuous Deployment":{"name":"Continuous Deployment","description":"Issues related to CD pipeline on git","color":"aea47c"},"Default branch":{"name":"Default branch","description":"Issues related to using a default branch on git","color":"195737"},"Git status":{"name":"Git status","description":"Issues related to information shown on git status modal or number of changes appearing in a branch","color":"c851b8"},"Git performance":{"name":"Git performance","description":"Issues related to perceived performance on any git operation","color":"189af6"},"Anvil team":{"name":"Anvil team","description":"issues related to the new layout system anvil","color":"798200"},"SDLC":{"name":"SDLC","description":"Issues related to software development lifecycle experiences","color":"bae511"},"Reconnect DS modal":{"name":"Reconnect DS modal","description":"Issues related to reconnect datasource modal post app import","color":"2e398b"},"Stability Pod":{"name":"Stability Pod","description":"For all issues/tasks to be prioritized under Stability pod","color":"86ddf6"},"Stability Issue":{"name":"Stability Issue","description":"Every issue handle by Stability Pod","color":"4d024a"},"Move to Postgres":{"name":"Move to Postgres","description":"Issues required to be solved for the move to Postgres as repository layer","color":"466ab1"},"User Session":{"name":"User Session","description":"Issues related to user sessions","color":"8255e5"},"IDE tabs":{"name":"IDE tabs","description":"query and js tabs","color":"1bb96a"},"Inviting Contribution":{"name":"Inviting Contribution","description":"Issues that we would like contributions to","color":""},"cypress-flaky-fix":{"name":"cypress-flaky-fix","description":"This label is auto-added when a PR which only has Cypress fixes are merged to release","color":"cd8bb6"},"Cypress flaky tests":{"name":"Cypress flaky tests","description":"Test scripts that need to be fixed on Cypress by dev or SDET","color":"cd8bb6"},"Help enterprise":{"name":"Help enterprise","description":"Requested by Appsmith customers or prospects","color":"FF8C00"},"Learnability":{"name":"Learnability","description":"Issues affecting the product learnability, making the product harder for new users.","color":"800c2f"},"ADS Spacing":{"name":"ADS Spacing","description":"","color":"686ebb"},"ads unit test":{"name":"ads unit test","description":"All issue related ads unit cases","color":"686ebb"},"ads revamp":{"name":"ads revamp","description":"All issues related to ads revamp.","color":"686ebb"},"Javascript Product":{"color":"709a21","name":"Javascript Product","description":"Issues related to users writing javascript in appsmith"},"IDE Product":{"color":"1bb96a","name":"IDE Product","description":"Issues related to the IDE Product"},"IDE Pod":{"color":"1bb96a","name":"IDE Pod","description":"Issues that new developers face while exploring the IDE"},"Accelerators Product":{"name":"Accelerators Product","description":"Issues related to app building accelerators","color":"f3fce6"},"Templates Product":{"name":"Templates Product","description":"Issues related to Templates","color":"f3fce6"},"Design System Product":{"name":"Design System Product","description":"Appsmith design system related issues","color":"2b4664"},"ads deduplication":{"name":"ads deduplication","description":"Replacing component with ADS components","color":"708943"},"Admin Settings Product":{"color":"708943","name":"Admin Settings Product","description":"Issues in admin settings pages"},"Appsmith AI":{"name":"Appsmith AI","description":"All issues related to the Appsmith AI datasource","color":"708943"},"Query & JS Pod":{"color":"ad1ea9","name":"Query & JS Pod","description":"Issues related to the query & JS Pod"},"RBAC Product":{"name":"RBAC Product","description":"Issues, requests and enhancements around RBAC.","color":""},"Workspace Product":{"name":"Workspace Product","description":"Issues related to workspaces","color":""},"CE Instance Usage":{"name":"CE Instance Usage","description":"For all issues relating to usage, licensing or billing on the CE instance","color":""},"Billing & Licensing Product":{"name":"Billing & Licensing Product","description":"Issues pertaining to licensing, billing and usage across self serve and enterprise customers","color":"466ab1"},"Platform Administration Pod":{"color":"446925","name":"Platform Administration Pod","description":"Issues related to platform administration & management"},"DB Infrastructure Pod":{"name":"DB Infrastructure Pod","description":"Pod to handle database infrastructure","color":"446925"},"Packages Product":{"name":"Packages Product","description":"Issues related to packages","color":"7e018f"},"Workflows Product":{"name":"Workflows Product","description":"Issues related to the workflows product","color":"446925"},"Debugger Product":{"color":"857f58","name":"Debugger Product","description":"Issues related to the debugger"},"Packages Pod":{"name":"Packages Pod","description":"issues that belong to the packages pod","color":"53742c"},"Environments Product":{"name":"Environments Product","description":"Issues related to datasource environments","color":"857f58"},"Custom Widgets":{"name":"Custom Widgets","description":"For all issues related to the custom widget project","color":"857f58"},"Branding Product":{"name":"Branding Product","description":"All issues under branding and whitelabelling appsmith ecosystem","color":"857f58"},"Widgets Product":{"name":"Widgets Product","description":"This label groups issues related to widgets","color":"ad1ea9"},"App Theming Product":{"name":"App Theming Product","description":"Items that are related to the App level theming controls epic","color":"48883f"},"UI Building Product":{"color":"48883f","name":"UI Building Product","description":"Issues related to the UI Building experience"},"Onboarding Product":{"color":"48883f","name":"Onboarding Product","description":"Issues related to onboarding new developers"},"Database Schema":{"name":"Database Schema","description":"Issues related to database schema","color":"48883f"},"Git Product":{"color":"7e018f","name":"Git Product","description":"Issues related to version control product"},"Embedding Apps Product":{"name":"Embedding Apps Product","description":"Issues related to embedding","color":"48883f"},"Integrations Product":{"name":"Integrations Product","description":"Issues related to a specific integration","color":"b9f21c"},"Feature Flagging":{"name":"Feature Flagging","description":"Anything related feature flagging","color":"4574ae"},"Audit Logs Product":{"name":"Audit Logs Product","description":"Audit trails to ensure data security","color":"4574ae"},"Identity & Authentication Product":{"name":"Identity & Authentication Product","description":"Issues related to user identity & authentication","color":"4574ae"},"Email verification":{"name":"Email verification","description":"Email verification issues","color":"4574ae"},"Artifact Platform Product":{"name":"Artifact Platform Product","description":"Issues related to the application platform","color":"4574ae"},"Git IA":{"name":"Git IA","description":"Issues related to Git IA changes","color":"df8bd6"},"Documentation Pod":{"name":"Documentation Pod","description":"Issues related to user education","color":"8c8c02"},"Branch management":{"name":"Branch management","description":"Issues related to using a branch management on git","color":"ebe6af"},"Reconfigure Datasource Modal":{"name":"Reconfigure Datasource Modal","description":"Issues related to reconfigure DS modal that comes after importing applications","color":"5ac17b"},"Setup Issues":{"name":"Setup Issues","description":"Issues related to setting up appsmith","color":"3fc837"},"Packages & Git Pod":{"name":"Packages & Git Pod","description":"All issues belonging to Packages and Git","color":"46ac0e"},"Git Platform":{"name":"Git Platform","description":"Issues related to the git & the app platform","color":"c9ab80"},"Entity Management":{"name":"Entity Management","description":"Copy / Move / Delete widgets / queries / datasources","color":"74c33c"},"Cypress":{"name":"Cypress","description":"Tasks related to Cypress automation","color":"67b83c"},"Query & Widgets Pod":{"name":"Query & Widgets Pod","description":"All issues related to Query, JS, Eval, and Widgets","color":"70b4e7"},"Cloud Billing":{"name":"Cloud Billing","description":"Label to aggregate tickets related to multi-tenancy/cloud billing.","color":"138d87"},"AWS Lambda":{"name":"AWS Lambda","description":"Lambda related issues","color":"c81d4a"},"Widgets & Accelerators Pod":{"name":"Widgets & Accelerators Pod","description":"Issues related to widgets & Accelerators","color":"ad1ea9"}},"success":true} \ No newline at end of file diff --git a/.github/workflows/ci-test-custom-script.yml b/.github/workflows/ci-test-custom-script.yml index cc67dddb0ed1..14d2ba7de6c7 100644 --- a/.github/workflows/ci-test-custom-script.yml +++ b/.github/workflows/ci-test-custom-script.yml @@ -370,6 +370,7 @@ jobs: CYPRESS_SNOWFLAKE_ACCOUNT_NAME: ${{ secrets.SNOWFLAKE_ACCOUNT_NAME }} CYPRESS_SNOWFLAKE_USERNAME: ${{ secrets.SNOWFLAKE_USERNAME }} CYPRESS_SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }} + CYPRESS_HUBSPOT_TOKEN: ${{ secrets.HUBSPOT_TOKEN }} NODE_ENV: development GITHUB_WORKFLOW : ${{ github.workflow }} run: | diff --git a/.github/workflows/ci-test-hosted.yml b/.github/workflows/ci-test-hosted.yml index 48eed24385d1..7ccd6173878e 100644 --- a/.github/workflows/ci-test-hosted.yml +++ b/.github/workflows/ci-test-hosted.yml @@ -247,6 +247,7 @@ jobs: CYPRESS_SNOWFLAKE_ACCOUNT_NAME: ${{ secrets.SNOWFLAKE_ACCOUNT_NAME }} CYPRESS_SNOWFLAKE_USERNAME: ${{ secrets.SNOWFLAKE_USERNAME }} CYPRESS_SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }} + CYPRESS_HUBSPOT_TOKEN: ${{ secrets.HUBSPOT_TOKEN }} NODE_ENV: development GITHUB_WORKFLOW : ${{ github.workflow }} run: | diff --git a/.github/workflows/ci-test-limited-with-count.yml b/.github/workflows/ci-test-limited-with-count.yml index 2faf3943fbee..cf9be992f9bf 100644 --- a/.github/workflows/ci-test-limited-with-count.yml +++ b/.github/workflows/ci-test-limited-with-count.yml @@ -426,6 +426,7 @@ jobs: CYPRESS_SNOWFLAKE_ACCOUNT_NAME: ${{ secrets.SNOWFLAKE_ACCOUNT_NAME }} CYPRESS_SNOWFLAKE_USERNAME: ${{ secrets.SNOWFLAKE_USERNAME }} CYPRESS_SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }} + CYPRESS_HUBSPOT_TOKEN: ${{ secrets.HUBSPOT_TOKEN }} NODE_ENV: development GITHUB_WORKFLOW : ${{ github.workflow }} run: | diff --git a/.github/workflows/ci-test-limited.yml b/.github/workflows/ci-test-limited.yml index da0343642d43..5a140dd58b63 100644 --- a/.github/workflows/ci-test-limited.yml +++ b/.github/workflows/ci-test-limited.yml @@ -342,6 +342,7 @@ jobs: CYPRESS_SNOWFLAKE_ACCOUNT_NAME: ${{ secrets.SNOWFLAKE_ACCOUNT_NAME }} CYPRESS_SNOWFLAKE_USERNAME: ${{ secrets.SNOWFLAKE_USERNAME }} CYPRESS_SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }} + CYPRESS_HUBSPOT_TOKEN: ${{ secrets.HUBSPOT_TOKEN }} GITHUB_WORKFLOW : ${{ github.workflow }} with: browser: ${{ env.BROWSER_PATH }} diff --git a/.gitignore b/.gitignore index 8d9bcfba4528..ce30cb8280c7 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ app/client/yalc.lock .idea .fleet/* app/client/.fleet/* +.lens # Observability related local storage utils/observability/tempo-data/* diff --git a/app/client/cypress/e2e/Regression/ClientSide/Branding/Branding_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Branding/Branding_spec.js index fe7929010443..ae4149c48ff8 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Branding/Branding_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Branding/Branding_spec.js @@ -40,17 +40,17 @@ describe("Branding", { tags: ["@tag.Settings"] }, () => { let favicon; let shades = {}; - it("1. check if localStorage is populated with tenantConfig values", () => { + it("1. check if localStorage is populated with organizationConfig values", () => { if (CURRENT_REPO === REPO.CE) { - const tenantConfig = localStorage.getItem("tenantConfig"); + const organizationConfig = localStorage.getItem("organizationConfig"); - expect(tenantConfig).to.be.null; + expect(organizationConfig).to.be.null; } if (CURRENT_REPO === REPO.EE) { - const tenantConfig = localStorage.getItem("tenantConfig"); + const organizationConfig = localStorage.getItem("organizationConfig"); - expect(tenantConfig).to.not.be.null; + expect(organizationConfig).to.not.be.null; } }); @@ -123,10 +123,10 @@ describe("Branding", { tags: ["@tag.Settings"] }, () => { ); }); - it("4. Check if localStorage is populated with tenantConfig values & form cannot be submitted", () => { + it("4. Check if localStorage is populated with organizationConfig values & form cannot be submitted", () => { if (CURRENT_REPO === REPO.CE) { - const tenantConfig = localStorage.getItem("tenantConfig"); - expect(tenantConfig).to.be.null; + const organizationConfig = localStorage.getItem("organizationConfig"); + expect(organizationConfig).to.be.null; cy.get(locators.submitButton).should("be.disabled"); } diff --git a/app/client/cypress/e2e/Regression/ClientSide/OtherUIFeatures/ApplicationURL_spec.js b/app/client/cypress/e2e/Regression/ClientSide/OtherUIFeatures/ApplicationURL_spec.js index c0abbd8e1dce..ffa6ccfaee53 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/OtherUIFeatures/ApplicationURL_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/OtherUIFeatures/ApplicationURL_spec.js @@ -144,10 +144,19 @@ describe("Slug URLs", { tags: ["@tag.AppUrl"] }, () => { it("4. Checks redirect url", () => { cy.url().then((url) => { - homePage.Signout(true); const redirectUrl = `${url}?embed=true&a=b`; + cy.stub(agHelper, "VisitNAssert").as("visitStub"); + + // Call your function that handles redirection agHelper.VisitNAssert(redirectUrl); - agHelper.AssertURL(`?redirectUrl=${encodeURIComponent(redirectUrl)}`); + + // Assert that the stubbed function was called with the correct redirectUrl + cy.get("@visitStub").should("have.been.calledWith", redirectUrl); + cy.wrap(redirectUrl).then((redirectUrl) => { + const encodedRedirectUrl = `?redirectUrl=${encodeURIComponent(redirectUrl)}`; + cy.log(encodedRedirectUrl); + agHelper.AssertURL(encodedRedirectUrl); + }); }); }); }); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Audio/AudioRecorder1_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Audio/AudioRecorder1_spec.ts index 1906771330e9..ad61fcc57a6e 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Audio/AudioRecorder1_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Audio/AudioRecorder1_spec.ts @@ -135,18 +135,18 @@ describe( agHelper.Sleep(1000); propPane.SelectColorFromColorPicker("iconcolor", -15); agHelper.AssertCSS( - widgetLocators.recorderComplete, + widgetLocators.recorderPrompt, "background-color", "rgb(255, 193, 61)", ); propPane.EnterJSContext("Box shadow", "Small"); agHelper - .GetElement(widgetLocators.recorderComplete) + .GetElement(widgetLocators.recorderPrompt) .should("have.css", "box-shadow") .and("not.eq", "none"); propPane.EnterJSContext("Border radius", "none"); agHelper.AssertCSS( - widgetLocators.recorderComplete, + widgetLocators.recorderPrompt, "border-radius", "3px", 0, diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/ListV2/PropertyPane_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/ListV2/PropertyPane_spec.ts index 6433daf8351c..5da2544f0d8f 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/ListV2/PropertyPane_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/ListV2/PropertyPane_spec.ts @@ -35,7 +35,58 @@ describe( deployMode.NavigateBacktoEditor(); }); - it("2. Toggle JS - Validate isVisible", function () { + it("2. Validate isVisible when list has selected item (#37683)", () => { + // Define selectors for widgets + const widgetSelector = (name: string) => `[data-widgetname-cy="${name}"]`; + const containerWidgetSelector = `[type="CONTAINER_WIDGET"]`; + + // Drag and drop the Button widget onto the canvas + // entityExplorer.DragDropWidgetNVerify("listwidgetv2", 300, 300); + entityExplorer.DragDropWidgetNVerify("buttonwidget"); + + // Set up the button to make the list visible when clicked + EditorNavigation.SelectEntityByName("Button1", EntityType.Widget); + propPane.EnterJSContext("onClick", `{{List1.setVisibility(true)}}`, true); + + // Set up the list widget to become invisible when an item is clicked + EditorNavigation.SelectEntityByName("List1", EntityType.Widget); + propPane.EnterJSContext( + "onItemClick", + `{{List1.setVisibility(false)}}`, + true, + ); + + // Deploy the application to test the visibility functionality + deployMode.DeployApp(); + + // Simulate a click on the first item in the list to hide the list + agHelper + .GetElement(widgetSelector("List1")) + .find(containerWidgetSelector) + .first() + .click({ force: true }); + agHelper.WaitUntilEleDisappear( + locators._widgetInDeployed(draggableWidgets.LIST_V2), + ); + + // Assert that the list widget is not visible after clicking an item + agHelper.AssertElementAbsence( + locators._widgetInDeployed(draggableWidgets.LIST_V2), + ); + + // Click the button to make the list visible again + agHelper.GetNClick(widgetSelector("Button1")); + + // Assert that the list widget is visible after clicking the button + agHelper.AssertElementVisibility( + locators._widgetInDeployed(draggableWidgets.LIST_V2), + ); + + // Navigate back to the editor after testing + deployMode.NavigateBacktoEditor(); + }); + + it("3. Toggle JS - Validate isVisible", function () { // Open Property pane agHelper.AssertElementVisibility( locators._widgetInDeployed(draggableWidgets.LIST_V2), @@ -61,7 +112,7 @@ describe( deployMode.NavigateBacktoEditor(); }); - it("3. Renaming the widget from Property pane and Entity explorer ", function () { + it("4. Renaming the widget from Property pane and Entity explorer ", function () { // Open Property pane EditorNavigation.SelectEntityByName("List1", EntityType.Widget); // Change the list widget name from property pane and Verify it @@ -73,7 +124,7 @@ describe( agHelper.AssertElementVisibility(locators._widgetName("List1")); }); - it("4. Item Spacing Validation ", function () { + it("5. Item Spacing Validation ", function () { EditorNavigation.SelectEntityByName("List1", EntityType.Widget); propPane.Search("item spacing"); propPane.UpdatePropertyFieldValue("Item Spacing (px)", "-1"); diff --git a/app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_MultiPart_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_MultiPart_Spec.ts index d3b96f76d4bc..4f40c54c6c68 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_MultiPart_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/ApiTests/API_MultiPart_Spec.ts @@ -15,6 +15,7 @@ import EditorNavigation, { AppSidebarButton, AppSidebar, } from "../../../../support/Pages/EditorNavigation"; +import PageList from "../../../../support/Pages/PageList"; describe( "Validate API request body panel", @@ -99,6 +100,7 @@ describe( }); it("7. Checks MultiPart form data for a File Type upload + Bug 12476", () => { + PageList.AddNewPage(); const imageNameToUpload = "ConcreteHouse.jpg"; agHelper.AddDsl("multiPartFormDataDsl"); @@ -111,7 +113,7 @@ describe( apiPage.EnterBodyFormData( "MULTIPART_FORM_DATA", "file", - "{{FilePicker1.files[0]}}", + "{{FilePicker1.files[0].data}}", "File", ); @@ -141,7 +143,7 @@ describe( EditorNavigation.SelectEntityByName("MultipartAPI", EntityType.Api); apiPage.ToggleOnPageLoadRun(false); //Bug 12476 - EditorNavigation.SelectEntityByName("Page1", EntityType.Page); + EditorNavigation.SelectEntityByName("Page2", EntityType.Page); deployMode.DeployApp(locators._buttonByText("Select Files")); agHelper.ClickButton("Select Files"); agHelper.UploadFile(imageNameToUpload); diff --git a/app/client/cypress/support/Objects/FeatureFlags.ts b/app/client/cypress/support/Objects/FeatureFlags.ts index d9fcbc2e6fb5..60434b52126f 100644 --- a/app/client/cypress/support/Objects/FeatureFlags.ts +++ b/app/client/cypress/support/Objects/FeatureFlags.ts @@ -1,6 +1,5 @@ import { LICENSE_FEATURE_FLAGS } from "../Constants"; import { ObjectsRegistry } from "./Registry"; -import produce from "immer"; const defaultFlags = { rollout_remove_feature_walkthrough_enabled: false, // remove this flag from here when it's removed from code @@ -40,12 +39,13 @@ export const getConsolidatedDataApi = ( res.statusCode === 500 ) { const originalResponse = res?.body; - const updatedResponse = produce(originalResponse, (draft: any) => { - draft.data.featureFlags.data = { - ...flags, - }; - }); - return res.send(updatedResponse); + try { + const updatedResponse = JSON.parse(JSON.stringify(originalResponse)); + updatedResponse.data.featureFlags.data = { ...flags }; + return res.send(updatedResponse); + } catch (e) { + cy.log(`vamsi error `, e); + } } }); }).as("getConsolidatedData"); @@ -90,18 +90,16 @@ export const featureFlagInterceptForLicenseFlags = () => { delete req.headers["if-none-match"]; if (res.statusCode === 200) { const originalResponse = res?.body; - const updatedResponse = produce(originalResponse, (draft: any) => { - draft.data.featureFlags.data = {}; - Object.keys(originalResponse.data.featureFlags.data).forEach( - (flag) => { - if (LICENSE_FEATURE_FLAGS.includes(flag)) { - draft.data.featureFlags.data[flag] = - originalResponse.data.featureFlags.data[flag]; - } - }, - ); - draft.data.featureFlags.data["release_app_sidebar_enabled"] = true; + const updatedResponse = JSON.parse(JSON.stringify(originalResponse)); + updatedResponse.data.featureFlags.data = {}; + Object.keys(originalResponse.data.featureFlags.data).forEach((flag) => { + if (LICENSE_FEATURE_FLAGS.includes(flag)) { + updatedResponse.data.featureFlags.data[flag] = + originalResponse.data.featureFlags.data[flag]; + } }); + updatedResponse.data.featureFlags.data["release_app_sidebar_enabled"] = + true; return res.send(updatedResponse); } }); diff --git a/app/client/package.json b/app/client/package.json index 43f757a30842..cdaa3998f2b2 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -91,6 +91,7 @@ "@types/d3-geo": "^3.1.0", "@types/google.maps": "^3.51.0", "@types/react-page-visibility": "^6.4.1", + "@types/react-window-infinite-loader": "^1.0.9", "@types/web": "^0.0.99", "@uppy/core": "^1.16.0", "@uppy/dashboard": "^1.16.0", @@ -203,6 +204,7 @@ "react-virtuoso": "^4.5.0", "react-webcam": "^7.0.1", "react-window": "^1.8.6", + "react-window-infinite-loader": "^1.0.10", "react-zoom-pan-pinch": "^1.6.1", "redux": "^4.0.1", "redux-form": "^8.2.6", diff --git a/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.stories.tsx b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.stories.tsx new file mode 100644 index 000000000000..16cf311d8ec4 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.stories.tsx @@ -0,0 +1,34 @@ +/* eslint-disable no-console */ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { MenuItem } from "../../Menu"; +import { EntityContextMenu } from "./EntityContextMenu"; + +const meta: Meta = { + title: "ADS/Templates/Entity Context Menu", + component: EntityContextMenu, +}; + +export default meta; + +type Story = StoryObj; + +export const Basic: Story = { + args: { + tooltipContent: "More actions", + children: ( + <> + + Rename + + + Copy + + + Delete + + + ), + }, +}; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.styles.ts b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.styles.ts new file mode 100644 index 000000000000..0faae06bd5dc --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.styles.ts @@ -0,0 +1,12 @@ +import styled from "styled-components"; + +import { MenuContent as ADSMenuContent } from "../../Menu"; + +export const MenuContent = styled(ADSMenuContent)` + width: 220px; + max-height: unset; +`; + +export const ButtonContainer = styled.div` + position: relative; +`; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.tsx b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.tsx new file mode 100644 index 000000000000..70cb3e8a9354 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/EntityContextMenu.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import { useToggle } from "usehooks-ts"; + +import { Button } from "../../Button"; +import { Menu, MenuTrigger } from "../../Menu"; +import { Tooltip } from "../../Tooltip"; + +import { + EntityClassNames, + DEFAULT_DATA_TEST_ID, + DEFAULT_TOOLTIP_CONTENT, +} from "./constants"; + +import * as Styled from "./EntityContextMenu.styles"; + +interface Props { + dataTestid?: string; + children?: React.ReactNode[] | React.ReactNode; + tooltipContent?: React.ReactNode; +} + +export const EntityContextMenu = (props: Props) => { + const { + children, + dataTestid = DEFAULT_DATA_TEST_ID, + tooltipContent = DEFAULT_TOOLTIP_CONTENT, + } = props; + + const [isMenuOpen, toggleMenuOpen] = useToggle(); + + return ( + + + + + + ); +}; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/constants.ts b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/constants.ts new file mode 100644 index 000000000000..ef1a1287cd40 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/constants.ts @@ -0,0 +1,7 @@ +export enum EntityClassNames { + CONTEXT_MENU = "entity-context-menu", + CONTEXT_MENU_CONTENT = "entity-context-menu-content", +} + +export const DEFAULT_DATA_TEST_ID = "t--more-action-trigger"; +export const DEFAULT_TOOLTIP_CONTENT = "More actions"; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/index.ts b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/index.ts new file mode 100644 index 000000000000..0c9f3e2fc2d1 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityContextMenu/index.ts @@ -0,0 +1 @@ +export { EntityContextMenu } from "./EntityContextMenu"; diff --git a/app/client/packages/design-system/ads/src/Templates/index.ts b/app/client/packages/design-system/ads/src/Templates/index.ts index 119bfd669a2f..00debb2e7685 100644 --- a/app/client/packages/design-system/ads/src/Templates/index.ts +++ b/app/client/packages/design-system/ads/src/Templates/index.ts @@ -4,3 +4,4 @@ export * from "./Sidebar"; export * from "./EditableEntityName"; export * from "./EditableDismissibleTab"; export * from "./EntityTabsHeader"; +export * from "./EntityContextMenu"; diff --git a/app/client/packages/design-system/widgets/package.json b/app/client/packages/design-system/widgets/package.json index c6bc9c064a5c..1d34149e1071 100644 --- a/app/client/packages/design-system/widgets/package.json +++ b/app/client/packages/design-system/widgets/package.json @@ -26,7 +26,7 @@ "@tabler/icons-react": "^3.10.0", "clsx": "^2.0.0", "lodash": "*", - "react-aria-components": "^1.2.1", + "react-aria-components": "^1.6.0", "react-markdown": "^9.0.1", "react-syntax-highlighter": "^15.5.0", "react-transition-group": "^4.4.5", diff --git a/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx index 160265802dff..db4e17fe9cab 100644 --- a/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx +++ b/app/client/packages/design-system/widgets/src/components/Calendar/src/CalendarHeading.tsx @@ -17,6 +17,8 @@ function CalendarHeading( [props, ref] = useContextProps(props, ref, HeadingContext); const state = useContext(CalendarStateContext); + if (!state) return null; + return (
diff --git a/app/client/packages/design-system/widgets/src/components/Checkbox/src/Checkbox.tsx b/app/client/packages/design-system/widgets/src/components/Checkbox/src/Checkbox.tsx index 685f7b262349..52a39f37020c 100644 --- a/app/client/packages/design-system/widgets/src/components/Checkbox/src/Checkbox.tsx +++ b/app/client/packages/design-system/widgets/src/components/Checkbox/src/Checkbox.tsx @@ -1,3 +1,4 @@ +import { clsx } from "clsx"; import React, { forwardRef } from "react"; import type { ForwardedRef } from "react"; import { Text, Icon } from "@appsmith/wds"; @@ -12,6 +13,7 @@ const _Checkbox = ( ) => { const { children, + className, isIndeterminate, isRequired, labelPosition = "end", @@ -22,7 +24,7 @@ const _Checkbox = ( diff --git a/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx b/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx index f57803332474..a912738c5a0f 100644 --- a/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx +++ b/app/client/packages/design-system/widgets/src/components/Datepicker/src/Datepicker.tsx @@ -94,7 +94,11 @@ export const DatePicker = (props: DatePickerProps) => { label="Time" maxValue={timeMaxValue} minValue={timeMinValue} - onChange={state.setTimeValue} + onChange={(value) => { + if (value) { + state.setTimeValue(value); + } + }} placeholderValue={timePlaceholder} value={state.timeValue} /> diff --git a/app/client/packages/design-system/widgets/src/components/FieldError/src/index.ts b/app/client/packages/design-system/widgets/src/components/FieldError/src/index.ts index f8de15b13fb0..bda1cd13a800 100644 --- a/app/client/packages/design-system/widgets/src/components/FieldError/src/index.ts +++ b/app/client/packages/design-system/widgets/src/components/FieldError/src/index.ts @@ -1,2 +1,3 @@ export * from "./FieldError"; export type { FieldErrorProps } from "./types"; +export { default as fieldErrorStyles } from "./styles.module.css"; diff --git a/app/client/packages/design-system/widgets/src/components/ListBox/src/ListBox.tsx b/app/client/packages/design-system/widgets/src/components/ListBox/src/ListBox.tsx index 75876ebaa68f..4f38cdfa4324 100644 --- a/app/client/packages/design-system/widgets/src/components/ListBox/src/ListBox.tsx +++ b/app/client/packages/design-system/widgets/src/components/ListBox/src/ListBox.tsx @@ -3,12 +3,13 @@ import styles from "./styles.module.css"; import { ListBox as HeadlessListBox } from "react-aria-components"; import type { ListBoxProps } from "./types"; +import clsx from "clsx"; export function ListBox(props: ListBoxProps) { - const { children, ...rest } = props; + const { children, className, ...rest } = props; return ( - + {children} ); diff --git a/app/client/packages/design-system/widgets/src/components/ListBox/src/index.ts b/app/client/packages/design-system/widgets/src/components/ListBox/src/index.ts index ae601b28db28..d18d014dd936 100644 --- a/app/client/packages/design-system/widgets/src/components/ListBox/src/index.ts +++ b/app/client/packages/design-system/widgets/src/components/ListBox/src/index.ts @@ -1,2 +1,2 @@ export { ListBox } from "./ListBox"; -export { default as listStyles } from "./styles.module.css"; +export { default as listBoxStyles } from "./styles.module.css"; diff --git a/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/ListBoxItem.tsx b/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/ListBoxItem.tsx index 353f2444a92e..acd3c0bfc4db 100644 --- a/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/ListBoxItem.tsx +++ b/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/ListBoxItem.tsx @@ -1,3 +1,4 @@ +import clsx from "clsx"; import React from "react"; import { Icon, Text } from "@appsmith/wds"; import { ListBoxItem as HeadlessListBoxItem } from "react-aria-components"; @@ -6,12 +7,21 @@ import styles from "./styles.module.css"; import type { ListBoxItemProps } from "./types"; export function ListBoxItem(props: ListBoxItemProps) { - const { children, icon, ...rest } = props; + const { children, className, icon, ...rest } = props; return ( - - {icon && } - {children} + + {typeof children === "function" ? ( + children + ) : ( + <> + {icon && } + {children} + + )} ); } diff --git a/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/types.ts b/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/types.ts index 613c3a88bbfb..c6436383c304 100644 --- a/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/types.ts +++ b/app/client/packages/design-system/widgets/src/components/ListBoxItem/src/types.ts @@ -1,5 +1,5 @@ -import type { ListBoxItemProps as AriaListBoxItemProps } from "react-aria-components"; import type { IconProps } from "@appsmith/wds"; +import type { ListBoxItemProps as AriaListBoxItemProps } from "react-aria-components"; export interface ListBoxItemProps extends AriaListBoxItemProps { icon?: IconProps["name"]; diff --git a/app/client/packages/design-system/widgets/src/components/Menu/src/Menu.tsx b/app/client/packages/design-system/widgets/src/components/Menu/src/Menu.tsx index 77cc1f6db4ab..6652e59f21eb 100644 --- a/app/client/packages/design-system/widgets/src/components/Menu/src/Menu.tsx +++ b/app/client/packages/design-system/widgets/src/components/Menu/src/Menu.tsx @@ -1,35 +1,30 @@ import { Popover, - listStyles, + listBoxStyles, useRootContainer, POPOVER_LIST_BOX_MAX_HEIGHT, } from "@appsmith/wds"; -import React, { createContext, useContext } from "react"; +import React from "react"; import { Menu as HeadlessMenu } from "react-aria-components"; import type { MenuProps } from "./types"; import clsx from "clsx"; -const MenuNestingContext = createContext(0); - export const Menu = (props: MenuProps) => { const { children, className, ...rest } = props; const root = useRootContainer(); - const nestingLevel = useContext(MenuNestingContext); - const isRootMenu = nestingLevel === 0; - return ( - - {/* Only the parent Popover should be placed in the root. Placing child popoves in root would cause the menu to function incorrectly */} - + - - {children} - - - + {children} + + ); }; diff --git a/app/client/packages/design-system/widgets/src/components/MultiSelect/index.ts b/app/client/packages/design-system/widgets/src/components/MultiSelect/index.ts new file mode 100644 index 000000000000..3bd16e178a03 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/MultiSelect/index.ts @@ -0,0 +1 @@ +export * from "./src"; diff --git a/app/client/packages/design-system/widgets/src/components/MultiSelect/src/MultiSelect.tsx b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/MultiSelect.tsx new file mode 100644 index 000000000000..4cf77ff138b0 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/MultiSelect.tsx @@ -0,0 +1,185 @@ +import clsx from "clsx"; +import React, { useRef, useState } from "react"; + +import { useField } from "react-aria"; +import { + DialogTrigger, + UNSTABLE_Autocomplete, + useFilter, + ButtonContext, + type Selection, +} from "react-aria-components"; + +import { setInteractionModality } from "@react-aria/interactions"; + +import { Text } from "../../Text"; +import styles from "./styles.module.css"; +import { ListBox } from "../../ListBox"; +import { + Popover, + POPOVER_LIST_BOX_MAX_HEIGHT, + useRootContainer, +} from "../../Popover"; +import { selectStyles } from "../../Select"; +import { TextField } from "../../TextField"; +import { FieldLabel } from "../../FieldLabel"; +import { textInputStyles } from "../../Input"; +import { inputFieldStyles } from "../../Field"; +import type { MultiSelectProps } from "./types"; +import { fieldErrorStyles } from "../../FieldError"; + +import { MultiSelectValue } from "./MultiSelectValue"; +import { Checkbox } from "../../Checkbox"; +import { ListBoxItem } from "../../ListBoxItem"; + +const EmptyState = () => { + return ( + + No options found + + ); +}; + +/** + * Note: React aria components does not provide us any mutliselect componennt or hooks for it. + * We are just replicating the behaviour of mutli select component with all available hooks and components. + * Few things are implemented manually like opening the popover on keydown or keyup when the button is focused + * or focusing the trigger on click of label. + * + * This is a temporary solution until we have a mutli select component from react aria components library. + */ +export const MultiSelect = ( + props: MultiSelectProps, +) => { + const { + contextualHelp, + defaultSelectedKeys = new Set(), + disabledKeys, + errorMessage, + excludeFromTabOrder, + isDisabled, + isInvalid, + isLoading, + isRequired, + items, + label, + onSelectionChange: onSelectionChangeProp, + placeholder, + selectedKeys: selectedKeysProp, + size, + } = props; + const root = useRootContainer(); + const [_selectedKeys, _setSelectedKeys] = useState(); + const selectedKeys = selectedKeysProp ?? _selectedKeys ?? defaultSelectedKeys; + const setSelectedKeys = onSelectionChangeProp ?? _setSelectedKeys; + const { labelProps } = useField(props); + const { contains } = useFilter({ sensitivity: "base" }); + const triggerRef = useRef(null); + // Note we have to use controlled state for the popover as we need a custom logic to open the popover + // for the usecase where we need to open the popover on keydown or keyup when the button is focused. + const [isOpen, setOpen] = useState(false); + + const onKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "ArrowDown" || e.key === "ArrowUp") { + setOpen(true); + } + }; + + const filter = (textValue: string, inputValue: string) => + contains(textValue, inputValue); + + return ( + +
+ {Boolean(label) && ( + { + if (triggerRef.current) { + triggerRef.current.focus(); + + setInteractionModality("keyboard"); + } + }} + > + {label} + + )} +
+ + + + + + + {(item: T) => ( + + {({ isSelected }) => ( + <> + + {item.label} + + )} + + )} + + + + +
+ {/* We can't use our FieldError component as it only works when used with FieldErrorContext. + We can use it in our Select and other inputs because the implementation is abstracted in the react aria components library. + But since for MultiSelect, we don't have any component from react-aria, we have to manually render the error message here. */} +
+ + {errorMessage} + +
+
+
+ ); +}; diff --git a/app/client/packages/design-system/widgets/src/components/MultiSelect/src/MultiSelectValue.tsx b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/MultiSelectValue.tsx new file mode 100644 index 000000000000..5492fb72eb2e --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/MultiSelectValue.tsx @@ -0,0 +1,167 @@ +import clsx from "clsx"; +import { type Selection, Button } from "react-aria-components"; +import { useResizeObserver, useValueEffect } from "@react-aria/utils"; +import React, { useCallback, useLayoutEffect, useMemo, useRef } from "react"; + +import { Icon } from "../../Icon"; +import { Text } from "../../Text"; +import { Spinner } from "../../Spinner"; +import { selectStyles } from "../../Select"; +import { textInputStyles } from "../../Input"; + +import styles from "./styles.module.css"; +import type { MultiSelectProps } from "./types"; + +interface MultiSelectValueProps { + excludeFromTabOrder?: boolean; + isDisabled?: boolean; + isLoading?: boolean; + selectedKeys?: Selection; + items?: Iterable<{ label: string; value: string }>; + placeholder?: string; + size?: MultiSelectProps["size"]; + triggerRef: React.RefObject; + isInvalid?: boolean; +} + +const MAX_ELLIPSIS_COUNT = 999; + +const MultiSelectValue: React.FC = ({ + excludeFromTabOrder, + isDisabled, + isInvalid, + isLoading, + items, + placeholder, + selectedKeys = new Set(), + size, + triggerRef, +}) => { + const domRef = useRef(null); + const selectedItems = useMemo(() => { + return [...selectedKeys].map((key) => + items ? Array.from(items).find((item) => item.value === key) : undefined, + ); + }, [items, selectedKeys]); + + const totalItems = Array.from(selectedKeys).length; + + const [{ visibleItems }, setVisibleItems] = useValueEffect({ + visibleItems: totalItems, + }); + + const updateOverflow = useCallback(() => { + const computeVisibleItems = (visibleItems: number) => { + if (domRef.current) { + const containerSize = domRef.current.getBoundingClientRect().width; + const listItems = Array.from( + domRef.current.children, + ) as HTMLLIElement[]; + const ellipisisItem = listItems.pop(); + const ellipisisItemWidth = + ellipisisItem?.getBoundingClientRect().width ?? 0; + let calculatedSize = 0; + let newVisibleItems = 0; + + for (const item of listItems) { + const itemWidth = item.getBoundingClientRect().width; + + calculatedSize += itemWidth; + + if ( + calculatedSize <= containerSize && + calculatedSize + ellipisisItemWidth < containerSize + ) { + newVisibleItems++; + } else { + break; + } + } + + return newVisibleItems; + } + + return visibleItems; + }; + + setVisibleItems(function* () { + yield { + visibleItems: totalItems, + }; + + const newVisibleItems = computeVisibleItems(totalItems); + const isMeasuring = newVisibleItems < totalItems && newVisibleItems > 0; + + yield { + visibleItems: newVisibleItems, + }; + + if (isMeasuring) { + yield { + visibleItems: computeVisibleItems(newVisibleItems), + }; + } + }); + }, [domRef, selectedKeys, setVisibleItems]); + + const parentRef = useMemo( + () => ({ + get current() { + return triggerRef.current?.parentElement; + }, + }), + [triggerRef], + ); + + useResizeObserver({ + ref: parentRef, + onResize: updateOverflow, + }); + + useLayoutEffect(updateOverflow, [updateOverflow, selectedKeys]); + + return ( + + ); +}; + +export { MultiSelectValue }; diff --git a/app/client/packages/design-system/widgets/src/components/MultiSelect/src/index.ts b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/index.ts new file mode 100644 index 000000000000..66baef198788 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/index.ts @@ -0,0 +1,2 @@ +export { MultiSelect } from "./MultiSelect"; +export type { MultiSelectProps } from "./types"; diff --git a/app/client/packages/design-system/widgets/src/components/MultiSelect/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/styles.module.css new file mode 100644 index 000000000000..e33d8926fb48 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/styles.module.css @@ -0,0 +1,62 @@ +.popover { + width: var(--trigger-width); + display: flex; + flex-direction: column; +} + +.listBoxItem { + display: flex; + align-items: center; + gap: var(--inner-spacing-2); +} + +.listBoxItem:first-of-type { + border-radius: 0; +} + +/* We don't want to default onliting that wds has on input, + * so we are overriding the default outline here. */ +.textField > div:has(> [data-input]) { + box-shadow: none; + border-bottom: var(--border-width-1) solid var(--color-bd); +} + +.textField + > div:has( + > [data-input]:is([data-focused], [data-focus-within]):not([data-readonly]) + ) { + box-shadow: none; + border-radius: 0; +} + +/* We don't want to show the border of input when the first item is focused + * as it conflicts with the border of the first item */ +.popover:has(.listBoxItem:first-of-type[data-focus-visible]) .textField > div { + border-color: transparent; +} + +.emptyState { + padding: var(--inner-spacing-4); + display: flex; + align-items: center; + justify-content: center; +} + +.multiSelectValue > * { + flex-shrink: 0; + min-width: 0; +} + +/* we are resevering max for 7 characters which describes "...+999" text */ +.ellipsisText { + max-width: 7ch; +} + +.selectedItemLabel { + flex-shrink: 0; +} + +/* This is required so that checkbox click event does not conflict with the listbox item click event */ +.listBoxItemCheckbox { + pointer-events: none; +} diff --git a/app/client/packages/design-system/widgets/src/components/MultiSelect/src/types.ts b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/types.ts new file mode 100644 index 000000000000..6ebbd1eee8b8 --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/MultiSelect/src/types.ts @@ -0,0 +1,40 @@ +import type { + ListBoxProps, + SelectProps as SpectrumSelectProps, + Selection, +} from "react-aria-components"; +import type { SIZES } from "../../../shared"; +import type { FieldProps } from "../../Field"; + +export interface MultiSelectProps + extends Omit< + SpectrumSelectProps, + "slot" | "selectedKey" | "onSelectionChange" + >, + FieldProps { + /** size of the select + * + * @default medium + */ + size?: Exclude; + /** + * The keys of the selected items. + */ + selectedKeys?: Selection; + /** + * Callback for when the selection changes. + */ + onSelectionChange?: (keys: Selection) => void; + /** + * The items to display in the list box. + */ + items: ListBoxProps["items"]; + /** + * The keys of the default selected items. + */ + defaultSelectedKeys?: Selection; + /** + * Whether the select is loading. + */ + isLoading?: boolean; +} diff --git a/app/client/packages/design-system/widgets/src/components/MultiSelect/stories/MultiSelect.stories.tsx b/app/client/packages/design-system/widgets/src/components/MultiSelect/stories/MultiSelect.stories.tsx new file mode 100644 index 000000000000..6f6981a721ea --- /dev/null +++ b/app/client/packages/design-system/widgets/src/components/MultiSelect/stories/MultiSelect.stories.tsx @@ -0,0 +1,83 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { Flex } from "@appsmith/wds"; +import type { SelectProps } from "@appsmith/wds"; +import { MultiSelect, SIZES } from "@appsmith/wds"; + +const items = Array.from({ length: 50 }, (_, i) => ({ + value: `Option ${i + 1}`, + label: `Option ${i + 1}`, +})); + +/** + * A multi select component is a component that allows users to select multiple options from a list. + */ +const meta: Meta = { + component: MultiSelect, + title: "WDS/Widgets/Multi Select", + args: { + label: "Label", + items, + placeholder: "Placeholder", + }, +}; + +export default meta; +type Story = StoryObj; + +export const Main: Story = {}; + +/** + * The component supports two sizes `small` and `medium`. Default size is `medium`. + */ +export const Sizes: Story = { + render: () => ( + + {Object.keys(SIZES) + .filter( + (size): size is NonNullable => + !["xSmall", "large"].includes(size), + ) + .map((size) => ( + + ))} + + ), +}; + +export const Loading: Story = { + args: { + placeholder: "Loading", + isLoading: true, + }, +}; + +export const Disabled: Story = { + args: { + placeholder: "Disabled", + isDisabled: true, + }, +}; + +export const ErrorMessage: Story = { + args: { + errorMessage: "There is an error", + isInvalid: true, + isRequired: true, + }, +}; + +export const ContextualHelp: Story = { + args: { + label: "Label", + placeholder: "Contextual Help Text", + contextualHelp: "This is a contextual help text", + }, +}; diff --git a/app/client/packages/design-system/widgets/src/components/Select/src/index.ts b/app/client/packages/design-system/widgets/src/components/Select/src/index.ts index b252bd3f677f..5626d3c154e1 100644 --- a/app/client/packages/design-system/widgets/src/components/Select/src/index.ts +++ b/app/client/packages/design-system/widgets/src/components/Select/src/index.ts @@ -1,2 +1,3 @@ export * from "./Select"; export type { SelectProps } from "./types"; +export { default as selectStyles } from "./styles.module.css"; diff --git a/app/client/packages/design-system/widgets/src/components/Select/stories/Select.stories.tsx b/app/client/packages/design-system/widgets/src/components/Select/stories/Select.stories.tsx index 05a82ae10f5a..b3f62af6bcf8 100644 --- a/app/client/packages/design-system/widgets/src/components/Select/stories/Select.stories.tsx +++ b/app/client/packages/design-system/widgets/src/components/Select/stories/Select.stories.tsx @@ -87,11 +87,13 @@ export const Validation: Story = { }} > - + {selectItems.map((item) => ( + + {item.label} + + ))} + diff --git a/app/client/packages/design-system/widgets/src/components/TextField/src/TextField.tsx b/app/client/packages/design-system/widgets/src/components/TextField/src/TextField.tsx index fd696a67dabd..43c97cc4ff6e 100644 --- a/app/client/packages/design-system/widgets/src/components/TextField/src/TextField.tsx +++ b/app/client/packages/design-system/widgets/src/components/TextField/src/TextField.tsx @@ -7,6 +7,7 @@ import type { TextFieldProps } from "./types"; export function TextField(props: TextFieldProps) { const { + className, contextualHelp, errorMessage, isDisabled, @@ -26,7 +27,7 @@ export function TextField(props: TextFieldProps) { return ( ` + position: relative; + grid-area: ${(props) => props.name}; +`; diff --git a/app/client/src/pages/Editor/IDE/LeftPane/PaneHeader.tsx b/app/client/src/IDE/Components/PaneHeader.tsx similarity index 100% rename from app/client/src/pages/Editor/IDE/LeftPane/PaneHeader.tsx rename to app/client/src/IDE/Components/PaneHeader.tsx diff --git a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/SectionHeader.tsx b/app/client/src/IDE/Components/SectionHeader.tsx similarity index 93% rename from app/client/src/pages/Editor/AppSettingsPane/AppSettings/SectionHeader.tsx rename to app/client/src/IDE/Components/SectionHeader.tsx index c48ad80ee14b..b2c1d54fe63b 100644 --- a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/SectionHeader.tsx +++ b/app/client/src/IDE/Components/SectionHeader.tsx @@ -37,7 +37,7 @@ const SubTitle = styled.div` color: var(--ads-v2-color-fg); `; -class SectionHeader extends React.Component { +export class SectionHeader extends React.Component { render(): React.ReactNode { return ( { ); } } - -export default SectionHeader; diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/SegmentAddHeader.tsx b/app/client/src/IDE/Components/SegmentAddHeader.tsx similarity index 100% rename from app/client/src/pages/Editor/IDE/EditorPane/components/SegmentAddHeader.tsx rename to app/client/src/IDE/Components/SegmentAddHeader.tsx diff --git a/app/client/src/IDE/Interfaces/GroupedAddOperations.ts b/app/client/src/IDE/Interfaces/GroupedAddOperations.ts new file mode 100644 index 000000000000..dd82c728ed5d --- /dev/null +++ b/app/client/src/IDE/Interfaces/GroupedAddOperations.ts @@ -0,0 +1,7 @@ +import type { ActionOperation } from "components/editorComponents/GlobalSearch/utils"; + +export type GroupedAddOperations = Array<{ + title?: string; + className: string; + operations: ActionOperation[]; +}>; diff --git a/app/client/src/IDE/hooks/index.ts b/app/client/src/IDE/hooks/index.ts index 8fe85b2a9d84..2ae8c7ef5671 100644 --- a/app/client/src/IDE/hooks/index.ts +++ b/app/client/src/IDE/hooks/index.ts @@ -1,2 +1,3 @@ export { useIsInSideBySideEditor } from "./useIsInSideBySideEditor"; export { useIsEditorInitialised } from "ee/IDE/hooks/useIsEditorInitialised"; +export { useCurrentAppState } from "./useCurrentAppState"; diff --git a/app/client/src/pages/Editor/IDE/hooks/useCurrentAppState.ts b/app/client/src/IDE/hooks/useCurrentAppState.ts similarity index 91% rename from app/client/src/pages/Editor/IDE/hooks/useCurrentAppState.ts rename to app/client/src/IDE/hooks/useCurrentAppState.ts index 9d36e085644a..485d1ee37cc7 100644 --- a/app/client/src/pages/Editor/IDE/hooks/useCurrentAppState.ts +++ b/app/client/src/IDE/hooks/useCurrentAppState.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { EditorState } from "IDE/enums"; +import { EditorState } from "../enums"; import { useLocation } from "react-router"; import { identifyEntityFromPath } from "navigation/FocusEntity"; diff --git a/app/client/src/IDE/hooks/useIsInSideBySideEditor.ts b/app/client/src/IDE/hooks/useIsInSideBySideEditor.ts index 8ceb91ba95a0..b2632c1a80aa 100644 --- a/app/client/src/IDE/hooks/useIsInSideBySideEditor.ts +++ b/app/client/src/IDE/hooks/useIsInSideBySideEditor.ts @@ -1,12 +1,10 @@ import { useSelector } from "react-redux"; import { useLocation } from "react-router"; -import { getIDEViewMode } from "../../selectors/ideSelectors"; -import { identifyEntityFromPath } from "../../navigation/FocusEntity"; -import { - getCurrentEntityInfo, - isInSideBySideEditor, -} from "../../pages/Editor/utils"; +import { getIDEViewMode } from "selectors/ideSelectors"; +import { identifyEntityFromPath } from "navigation/FocusEntity"; +import { isInSideBySideEditor } from "../utils/isInSideBySideEditor"; +import { getCurrentEntityInfo } from "../utils/getCurrentEntityInfo"; /** * Checks if current component is in side-by-side editor mode. diff --git a/app/client/src/pages/Editor/IDE/EditorPane/hooks/useNameEditorState.ts b/app/client/src/IDE/hooks/useNameEditorState.ts similarity index 75% rename from app/client/src/pages/Editor/IDE/EditorPane/hooks/useNameEditorState.ts rename to app/client/src/IDE/hooks/useNameEditorState.ts index 364bf7a23432..db82e52ddbcd 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/hooks/useNameEditorState.ts +++ b/app/client/src/IDE/hooks/useNameEditorState.ts @@ -1,7 +1,9 @@ import { useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { initExplorerEntityNameEdit } from "actions/explorerActions"; -import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; +import { + endExplorerEntityNameEdit, + initExplorerEntityNameEdit, +} from "actions/explorerActions"; import { getUpdatingEntity, getEditingEntityName, @@ -22,9 +24,7 @@ export function useNameEditorState() { ); const exitEditMode = useCallback(() => { - dispatch({ - type: ReduxActionTypes.END_EXPLORER_ENTITY_NAME_EDIT, - }); + dispatch(endExplorerEntityNameEdit()); }, [dispatch]); return { diff --git a/app/client/src/IDE/utils/getCurrentEntityInfo.ts b/app/client/src/IDE/utils/getCurrentEntityInfo.ts new file mode 100644 index 000000000000..f3850d05d801 --- /dev/null +++ b/app/client/src/IDE/utils/getCurrentEntityInfo.ts @@ -0,0 +1,66 @@ +import { FocusEntity } from "navigation/FocusEntity"; +import { + EditorEntityTab, + EditorEntityTabState, +} from "../Interfaces/EditorTypes"; + +/** + * Resolve segment and segmentMode based on entity type. + */ +export function getCurrentEntityInfo(entity: FocusEntity) { + switch (entity) { + case FocusEntity.QUERY: + case FocusEntity.API: + case FocusEntity.QUERY_MODULE_INSTANCE: + return { + segment: EditorEntityTab.QUERIES, + segmentMode: EditorEntityTabState.Edit, + }; + case FocusEntity.QUERY_LIST: + return { + segment: EditorEntityTab.QUERIES, + segmentMode: EditorEntityTabState.List, + }; + case FocusEntity.QUERY_ADD: + return { + segment: EditorEntityTab.QUERIES, + segmentMode: EditorEntityTabState.Add, + }; + case FocusEntity.JS_OBJECT: + case FocusEntity.JS_MODULE_INSTANCE: + return { + segment: EditorEntityTab.JS, + segmentMode: EditorEntityTabState.Edit, + }; + case FocusEntity.JS_OBJECT_ADD: + return { + segment: EditorEntityTab.JS, + segmentMode: EditorEntityTabState.Add, + }; + case FocusEntity.JS_OBJECT_LIST: + return { + segment: EditorEntityTab.JS, + segmentMode: EditorEntityTabState.List, + }; + case FocusEntity.CANVAS: + return { + segment: EditorEntityTab.UI, + segmentMode: EditorEntityTabState.Add, + }; + case FocusEntity.WIDGET: + return { + segment: EditorEntityTab.UI, + segmentMode: EditorEntityTabState.Edit, + }; + case FocusEntity.WIDGET_LIST: + return { + segment: EditorEntityTab.UI, + segmentMode: EditorEntityTabState.List, + }; + default: + return { + segment: EditorEntityTab.UI, + segmentMode: EditorEntityTabState.Add, + }; + } +} diff --git a/app/client/src/IDE/utils/isInSideBySideEditor.ts b/app/client/src/IDE/utils/isInSideBySideEditor.ts new file mode 100644 index 000000000000..c06060396a0a --- /dev/null +++ b/app/client/src/IDE/utils/isInSideBySideEditor.ts @@ -0,0 +1,21 @@ +import { EditorEntityTab, EditorViewMode } from "../Interfaces/EditorTypes"; +import { EditorState } from "../enums"; + +/** + * Check if use is currently working is side-by-side editor mode. + */ +export function isInSideBySideEditor({ + appState, + segment, + viewMode, +}: { + viewMode: EditorViewMode; + appState: EditorState; + segment: EditorEntityTab; +}) { + return ( + viewMode === EditorViewMode.SplitScreen && + appState === EditorState.EDITOR && + segment !== EditorEntityTab.UI + ); +} diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx index 5aa104dcfd69..bc9bdb0316a2 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/BindDataButton.tsx @@ -25,7 +25,7 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import { getHasManagePagePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; import { getWidgets } from "sagas/selectors"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsStructureReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsStructureReducer"; import { WDS_V2_WIDGET_MAP } from "modules/ui-builder/ui/wds/constants"; import { getNextWidgetName } from "sagas/WidgetOperationUtils"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; diff --git a/app/client/src/WidgetProvider/factory/index.tsx b/app/client/src/WidgetProvider/factory/index.tsx index f863b6530d88..99930aa24dff 100644 --- a/app/client/src/WidgetProvider/factory/index.tsx +++ b/app/client/src/WidgetProvider/factory/index.tsx @@ -36,7 +36,7 @@ import type { RegisteredWidgetFeatures } from "../../utils/WidgetFeatures"; import type { SetterConfig } from "entities/AppTheming"; import { freeze, memoize } from "./decorators"; import { create } from "mutative"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { CopiedWidgetData, PasteDestinationInfo, diff --git a/app/client/src/actions/autoLayoutActions.ts b/app/client/src/actions/autoLayoutActions.ts index 041cb958478b..af71b32c6abc 100644 --- a/app/client/src/actions/autoLayoutActions.ts +++ b/app/client/src/actions/autoLayoutActions.ts @@ -1,6 +1,6 @@ import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import type { LayoutSystemTypes } from "layoutSystems/types"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { CONVERSION_STATES, SnapshotDetails, diff --git a/app/client/src/actions/controlActions.tsx b/app/client/src/actions/controlActions.tsx index 84aa5c581869..9111de3a6ce2 100644 --- a/app/client/src/actions/controlActions.tsx +++ b/app/client/src/actions/controlActions.tsx @@ -1,6 +1,6 @@ import type { ReduxAction, ReduxActionType } from "./ReduxActionTypes"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import type { UpdateWidgetsPayload } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { UpdateWidgetsPayload } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { DynamicPath } from "utils/DynamicBindingUtils"; export const updateWidgetPropertyRequest = ( diff --git a/app/client/src/actions/pageActions.tsx b/app/client/src/actions/pageActions.tsx index 54c3d87cb6fe..e89c2b121745 100644 --- a/app/client/src/actions/pageActions.tsx +++ b/app/client/src/actions/pageActions.tsx @@ -17,7 +17,7 @@ import type { } from "api/PageApi"; import type { UrlDataState } from "reducers/entityReducers/appReducer"; import type { APP_MODE } from "entities/App"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { ENTITY_TYPE } from "ee/entities/AppsmithConsole/utils"; import type { Replayable } from "entities/Replay/ReplayEntity/ReplayEditor"; import * as Sentry from "@sentry/react"; diff --git a/app/client/src/ce/AppRouter.tsx b/app/client/src/ce/AppRouter.tsx index 0675d4ba7bc1..6d4f72eea78c 100644 --- a/app/client/src/ce/AppRouter.tsx +++ b/app/client/src/ce/AppRouter.tsx @@ -32,7 +32,7 @@ import { } from "constants/routes"; import WorkspaceLoader from "pages/workspace/loader"; import ApplicationListLoader from "pages/Applications/loader"; -import EditorLoader from "pages/Editor/loader"; +import AppIDE from "pages/AppIDE/AppIDELoader"; import AppViewerLoader from "pages/AppViewer/loader"; import LandingScreen from "../LandingScreen"; import UserAuth from "pages/UserAuth"; @@ -52,7 +52,7 @@ import SignupSuccess from "pages/setup/SignupSuccess"; import type { ERROR_CODES } from "ee/constants/ApiConstants"; import TemplatesListLoader from "pages/Templates/loader"; import { getCurrentUser as getCurrentUserSelector } from "selectors/usersSelectors"; -import { getTenantPermissions } from "ee/selectors/tenantSelectors"; +import { getOrganizationPermissions } from "ee/selectors/organizationSelectors"; import useBrandingTheme from "utils/hooks/useBrandingTheme"; import RouteChangeListener from "RouteChangeListener"; import { initCurrentPage } from "../actions/initActions"; @@ -71,7 +71,7 @@ export const loadingIndicator = ; export function Routes() { const user = useSelector(getCurrentUserSelector); - const tenantPermissions = useSelector(getTenantPermissions); + const organizationPermissions = useSelector(getOrganizationPermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); useFeatureFlagOverride(); @@ -102,7 +102,7 @@ export function Routes() { : getAdminSettingsPath( isFeatureEnabled, user?.isSuperUser || false, - tenantPermissions, + organizationPermissions, ) } /> @@ -116,7 +116,7 @@ export function Routes() { exact path={CUSTOM_WIDGETS_DEPRECATED_EDITOR_ID_PATH} /> - + - + + {/* @@ -161,7 +161,7 @@ export default function AppRouter() { const isLoading = isConsolidatedPageLoading; - // hide the top loader once the tenant is loaded + // hide the top loader once the organization is loaded useEffect(() => { if (!isLoading) { const loader = document.getElementById("loader") as HTMLDivElement; diff --git a/app/client/src/ce/actions/organizationActions.ts b/app/client/src/ce/actions/organizationActions.ts new file mode 100644 index 000000000000..e65b80af230f --- /dev/null +++ b/app/client/src/ce/actions/organizationActions.ts @@ -0,0 +1,21 @@ +import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; +import type { UpdateOrganizationConfigRequest } from "ee/api/OrganizationApi"; +import type { ApiResponse } from "api/ApiResponses"; + +export const getCurrentOrganization = ( + isBackgroundRequest = true, + organizationConfig?: ApiResponse, +) => ({ + type: ReduxActionTypes.FETCH_CURRENT_ORGANIZATION_CONFIG, + payload: { + isBackgroundRequest, + organizationConfig, + }, +}); + +export const updateOrganizationConfig = ( + payload: UpdateOrganizationConfigRequest, +) => ({ + type: ReduxActionTypes.UPDATE_ORGANIZATION_CONFIG, + payload, +}); diff --git a/app/client/src/ce/actions/tenantActions.ts b/app/client/src/ce/actions/tenantActions.ts deleted file mode 100644 index 6e4668f936dd..000000000000 --- a/app/client/src/ce/actions/tenantActions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import type { UpdateTenantConfigRequest } from "ee/api/TenantApi"; -import type { ApiResponse } from "api/ApiResponses"; - -export const getCurrentTenant = ( - isBackgroundRequest = true, - tenantConfig?: ApiResponse, -) => ({ - type: ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG, - payload: { - isBackgroundRequest, - tenantConfig, - }, -}); - -export const updateTenantConfig = (payload: UpdateTenantConfigRequest) => ({ - type: ReduxActionTypes.UPDATE_TENANT_CONFIG, - payload, -}); diff --git a/app/client/src/ce/api/OrganizationApi.ts b/app/client/src/ce/api/OrganizationApi.ts new file mode 100644 index 000000000000..4476731652af --- /dev/null +++ b/app/client/src/ce/api/OrganizationApi.ts @@ -0,0 +1,46 @@ +import type { AxiosPromise, AxiosRequestConfig } from "axios"; + +import Api from "api/Api"; +import type { ApiResponse } from "api/ApiResponses"; + +export type FetchCurrentOrganizationConfigResponse = ApiResponse<{ + userPermissions: string[]; + organizationConfiguration: Record; + new: boolean; +}>; + +export type UpdateOrganizationConfigResponse = ApiResponse<{ + organizationConfiguration: Record; +}>; + +export interface UpdateOrganizationConfigRequest { + organizationConfiguration: Record; + needsRefresh?: boolean; + isOnlyOrganizationSettings?: boolean; + apiConfig?: AxiosRequestConfig; +} + +export class OrganizationApi extends Api { + static tenantsUrl = "v1/tenants"; + + static async fetchCurrentOrganizationConfig(): Promise< + AxiosPromise + > { + return Api.get(`${OrganizationApi.tenantsUrl}/current`); + } + + static async updateOrganizationConfig( + request: UpdateOrganizationConfigRequest, + ): Promise> { + return Api.put( + `${OrganizationApi.tenantsUrl}`, + request.organizationConfiguration, + null, + { + ...(request.apiConfig || {}), + }, + ); + } +} + +export default OrganizationApi; diff --git a/app/client/src/ce/api/TenantApi.ts b/app/client/src/ce/api/TenantApi.ts deleted file mode 100644 index 81560d029f8e..000000000000 --- a/app/client/src/ce/api/TenantApi.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { AxiosPromise, AxiosRequestConfig } from "axios"; - -import Api from "api/Api"; -import type { ApiResponse } from "api/ApiResponses"; - -export type FetchCurrentTenantConfigResponse = ApiResponse<{ - userPermissions: string[]; - tenantConfiguration: Record; - new: boolean; -}>; - -export type UpdateTenantConfigResponse = ApiResponse<{ - tenantConfiguration: Record; -}>; - -export interface UpdateTenantConfigRequest { - tenantConfiguration: Record; - needsRefresh?: boolean; - isOnlyTenantSettings?: boolean; - apiConfig?: AxiosRequestConfig; -} - -export class TenantApi extends Api { - static tenantsUrl = "v1/tenants"; - - static async fetchCurrentTenantConfig(): Promise< - AxiosPromise - > { - return Api.get(`${TenantApi.tenantsUrl}/current`); - } - - static async updateTenantConfig( - request: UpdateTenantConfigRequest, - ): Promise> { - return Api.put( - `${TenantApi.tenantsUrl}`, - request.tenantConfiguration, - null, - { - ...(request.apiConfig || {}), - }, - ); - } -} - -export default TenantApi; diff --git a/app/client/src/ce/constants/PackageConstants.ts b/app/client/src/ce/constants/PackageConstants.ts index 5d0ea3610732..a69822d2f770 100644 --- a/app/client/src/ce/constants/PackageConstants.ts +++ b/app/client/src/ce/constants/PackageConstants.ts @@ -11,6 +11,16 @@ export interface Package { modifiedBy: string; modifiedAt: string; userPermissions: string[]; + gitArtifactMetadata?: { + branchName: string; + defaultBranchName: string; + remoteUrl: string; + repoName: string; + browserSupportedUrl?: string; + isRepoPrivate?: boolean; + browserSupportedRemoteUrl: string; + defaultApplicationId: string; + }; } export type PackageMetadata = Package; diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index bacbf4ce3d6b..769eebc4977a 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -1197,19 +1197,21 @@ const AppSettingsActionTypes = { "UPDATE_APP_SETTINGS_PANE_SELECTED_TAB", }; -const TenantActionTypes = { - FETCH_CURRENT_TENANT_CONFIG: "FETCH_CURRENT_TENANT_CONFIG", - FETCH_CURRENT_TENANT_CONFIG_SUCCESS: "FETCH_CURRENT_TENANT_CONFIG_SUCCESS", - UPDATE_TENANT_CONFIG: "UPDATE_TENANT_CONFIG", - UPDATE_TENANT_CONFIG_SUCCESS: "UPDATE_TENANT_CONFIG_SUCCESS", +const OrganizationActionTypes = { + FETCH_CURRENT_ORGANIZATION_CONFIG: "FETCH_CURRENT_ORGANIZATION_CONFIG", + FETCH_CURRENT_ORGANIZATION_CONFIG_SUCCESS: + "FETCH_CURRENT_ORGANIZATION_CONFIG_SUCCESS", + UPDATE_ORGANIZATION_CONFIG: "UPDATE_ORGANIZATION_CONFIG", + UPDATE_ORGANIZATION_CONFIG_SUCCESS: "UPDATE_ORGANIZATION_CONFIG_SUCCESS", FETCH_PRODUCT_ALERT_INIT: "FETCH_PRODUCT_ALERT_INIT", FETCH_PRODUCT_ALERT_SUCCESS: "FETCH_PRODUCT_ALERT_SUCCESS", UPDATE_PRODUCT_ALERT_CONFIG: "UPDATE_PRODUCT_ALERT_CONFIG", }; -const TenantActionErrorTypes = { - FETCH_CURRENT_TENANT_CONFIG_ERROR: "FETCH_CURRENT_TENANT_CONFIG_ERROR", - UPDATE_TENANT_CONFIG_ERROR: "UPDATE_TENANT_CONFIG_ERROR", +const OrganizationActionErrorTypes = { + FETCH_CURRENT_ORGANIZATION_CONFIG_ERROR: + "FETCH_CURRENT_ORGANIZATION_CONFIG_ERROR", + UPDATE_ORGANIZATION_CONFIG_ERROR: "UPDATE_ORGANIZATION_CONFIG_ERROR", FETCH_PRODUCT_ALERT_FAILED: "FETCH_PRODUCT_ALERT_FAILED", }; @@ -1290,7 +1292,7 @@ export const ReduxActionTypes = { ...SnippingModeActionTypes, ...TableWidgetActionsTypes, ...TemplateActionsTypes, - ...TenantActionTypes, + ...OrganizationActionTypes, ...ThemeActionTypes, ...UserAuthActionTypes, ...UserProfileActionTypes, @@ -1320,7 +1322,7 @@ export const ReduxActionErrorTypes = { ...PlatformActionErrorTypes, ...PluginActionErrorTypes, ...TemplateActionErrorTypes, - ...TenantActionErrorTypes, + ...OrganizationActionErrorTypes, ...UserAuthActionErrorTypes, ...UserProfileActionErrorTypes, ...WidgetCanvasActionErrorTypes, @@ -1336,7 +1338,7 @@ export const toastMessageErrorTypes = { ...GitActionErrorTypes, ...ImportExportActionErrorTypes, ...PlatformActionErrorTypes, - ...TenantActionErrorTypes, + ...OrganizationActionErrorTypes, ...UserAuthActionErrorTypes, ...UserProfileActionErrorTypes, ...WorkspaceActionErrorTypes, diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 290161943e6a..7b254ce2da2a 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -1151,8 +1151,8 @@ export const NO_COPIED_SSH_KEY = () => "Could not copy SSH key"; // Git Branch Protection export const UPDATE = () => "Update"; export const DEFAULT_BRANCH = () => "Default branch"; -export const DEFAULT_BRANCH_DESC = () => - "This is the base branch of the app. Users launching the app from the dashboard will see the deployed version from this branch."; +export const DEFAULT_BRANCH_DESC = (artifactNoun: string) => + `This is the base branch of the ${artifactNoun}. Users launching the ${artifactNoun} from the dashboard will see the deployed version from this branch.`; export const BRANCH_PROTECTION = () => "Branch protection"; export const BRANCH_PROTECTION_DESC = () => "Protected branches enable you to enforce Git workflows. Changes to the app are not allowed in the protected branches."; @@ -1179,17 +1179,22 @@ export const BRANCH_PROTECTION_PROTECTED = () => "Protected"; export const GIT_CONNECT_SUCCESS_TITLE = () => "Successfully connected to Git"; export const GIT_CONNECT_SUCCESS_MESSAGE = () => "Now you can start collaborating with your team members by committing, merging and deploying your app"; -export const GIT_CONNECT_SUCCESS_ACTION_CONTINUE = () => - "Continue to edit application"; +export const GIT_CONNECT_SUCCESS_ACTION_CONTINUE = ( + artifactType: string = "applications", +) => `Continue to edit ${artifactType}`; export const GIT_CONNECT_SUCCESS_ACTION_SETTINGS = () => "Protect your branch"; export const GIT_CONNECT_SUCCESS_PROTECTION_MSG = () => "We recommend protecting your default branch to have a seamless collaboration."; +export const GIT_CONNECT_SUCCESS_GENERIC_MESSAGE = (artifactType: string) => + `You're all set! Your ${artifactType} is now connected to Git.`; export const GIT_CONNECT_SUCCESS_REPO_NAME = () => "Repository name"; export const GIT_CONNECT_SUCCESS_DEFAULT_BRANCH = () => "Default branch"; export const GIT_CONNECT_SUCCESS_DEFAULT_BRANCH_TOOLTIP = () => "This is the base branch of the app. Users launching the app from the dashboard will see the deployed version from this branch."; export const GIT_CONNECT_SUCCESS_PROTECTION_DOC_CTA = () => "Learn more about branch protection"; +export const GIT_CONNECT_SUCCESS_GENERIC_DOC_CTA = () => + "Learn more about how to work with Git."; // Git Connection Success end export const GENERAL = () => "General"; diff --git a/app/client/src/ce/constants/tenantConstants.ts b/app/client/src/ce/constants/organizationConstants.ts similarity index 88% rename from app/client/src/ce/constants/tenantConstants.ts rename to app/client/src/ce/constants/organizationConstants.ts index 8ab31888f464..0168039c00bd 100644 --- a/app/client/src/ce/constants/tenantConstants.ts +++ b/app/client/src/ce/constants/organizationConstants.ts @@ -1,4 +1,4 @@ -export const tenantConfigConnection: string[] = [ +export const organizationConfigConnection: string[] = [ "instanceName", "googleMapsKey", "emailVerificationEnabled", diff --git a/app/client/src/ce/entities/DataTree/types.ts b/app/client/src/ce/entities/DataTree/types.ts index 0c1818d7a502..2073f72df38c 100644 --- a/app/client/src/ce/entities/DataTree/types.ts +++ b/app/client/src/ce/entities/DataTree/types.ts @@ -10,7 +10,7 @@ import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsR import type { WidgetConfigProps } from "WidgetProvider/constants"; import type { ActionDataState } from "ee/reducers/entityReducers/actionsReducer"; import type { WidgetProps } from "widgets/BaseWidget"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { MetaState } from "reducers/entityReducers/metaReducer"; import type { AppDataState } from "reducers/entityReducers/appReducer"; import type { JSCollectionDataState } from "ee/reducers/entityReducers/jsActionsReducer"; diff --git a/app/client/src/ce/navigation/FocusSetters.ts b/app/client/src/ce/navigation/FocusSetters.ts index 4d5aa3197b08..d96bfdf97c03 100644 --- a/app/client/src/ce/navigation/FocusSetters.ts +++ b/app/client/src/ce/navigation/FocusSetters.ts @@ -7,7 +7,7 @@ import { import { PluginType } from "entities/Plugin"; import type { FocusEntityInfo } from "navigation/FocusEntity"; import { FocusEntity } from "navigation/FocusEntity"; -import { getQueryEntityItemUrl } from "ee/pages/Editor/IDE/EditorPane/Query/utils/getQueryEntityItemUrl"; +import { getQueryEntityItemUrl } from "ee/pages/AppIDE/layouts/routers/utils/getQueryEntityItemUrl"; export function setSelectedDatasource(id?: string) { if (id) { diff --git a/app/client/src/ce/pages/AdminSettings/config/authentication.tsx b/app/client/src/ce/pages/AdminSettings/config/authentication.tsx index 2d46cae39c18..8cb3b1544cde 100644 --- a/app/client/src/ce/pages/AdminSettings/config/authentication.tsx +++ b/app/client/src/ce/pages/AdminSettings/config/authentication.tsx @@ -22,7 +22,7 @@ import { useSelector } from "react-redux"; import { getThirdPartyAuths, getIsFormLoginEnabled, -} from "ee/selectors/tenantSelectors"; +} from "ee/selectors/organizationSelectors"; import { FORM_LOGIN_DESC, GITHUB_AUTH_DESC, diff --git a/app/client/src/ce/pages/AdminSettings/config/general.tsx b/app/client/src/ce/pages/AdminSettings/config/general.tsx index ce70177f71f5..ae0ba589e46d 100644 --- a/app/client/src/ce/pages/AdminSettings/config/general.tsx +++ b/app/client/src/ce/pages/AdminSettings/config/general.tsx @@ -110,7 +110,7 @@ export const APPSMITH_IS_ATOMIC_PUSH_ALLOWED: Setting = { category: SettingCategories.GENERAL, controlType: SettingTypes.CHECKBOX, label: "Allow atomic pushes", - text: "Git operations on this tenant should attempt to perform pushes atomically", + text: "Git operations on this organization should attempt to perform pushes atomically", }; export const APPSMITH_ALLOWED_FRAME_ANCESTORS_SETTING: Setting = { diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSUrl.test.ts b/app/client/src/ce/pages/AppIDE/components/JSAdd/getJSUrl.test.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSUrl.test.ts rename to app/client/src/ce/pages/AppIDE/components/JSAdd/getJSUrl.test.ts diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSUrl.ts b/app/client/src/ce/pages/AppIDE/components/JSAdd/getJSUrl.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSUrl.ts rename to app/client/src/ce/pages/AppIDE/components/JSAdd/getJSUrl.ts diff --git a/app/client/src/ce/pages/AppIDE/components/JSAdd/hooks.tsx b/app/client/src/ce/pages/AppIDE/components/JSAdd/hooks.tsx new file mode 100644 index 000000000000..70022fd6bfd4 --- /dev/null +++ b/app/client/src/ce/pages/AppIDE/components/JSAdd/hooks.tsx @@ -0,0 +1,22 @@ +import { createNewJSCollection } from "actions/jsPaneActions"; +import type { GroupedAddOperations } from "IDE/Interfaces/GroupedAddOperations"; +import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages"; +import { JsFileIconV2 } from "pages/Editor/Explorer/ExplorerIcons"; +import { SEARCH_ITEM_TYPES } from "components/editorComponents/GlobalSearch/utils"; + +export const useGroupedAddJsOperations = (): GroupedAddOperations => { + return [ + { + className: "t--blank-js", + operations: [ + { + title: createMessage(EDITOR_PANE_TEXTS.js_blank_object_item), + desc: "", + icon: JsFileIconV2(16, 16), + kind: SEARCH_ITEM_TYPES.actionOperation, + action: (pageId) => createNewJSCollection(pageId, "ENTITY_EXPLORER"), + }, + ], + }, + ]; +}; diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/__tests__/JS/useGroupAddJsOperations.test.ts b/app/client/src/ce/pages/AppIDE/components/JSAdd/useGroupAddJsOperations.test.ts similarity index 91% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/__tests__/JS/useGroupAddJsOperations.test.ts rename to app/client/src/ce/pages/AppIDE/components/JSAdd/useGroupAddJsOperations.test.ts index c15389a3ae9d..7c167512d92e 100644 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/__tests__/JS/useGroupAddJsOperations.test.ts +++ b/app/client/src/ce/pages/AppIDE/components/JSAdd/useGroupAddJsOperations.test.ts @@ -1,5 +1,5 @@ import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages"; -import { useGroupedAddJsOperations } from "../../JS/hooks"; +import { useGroupedAddJsOperations } from "./hooks"; describe("useGroupedAddJsOperations", () => { it("returns an array of grouped operations", () => { diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/ListItem.tsx b/app/client/src/ce/pages/AppIDE/components/JSListItem/ListItem.tsx similarity index 68% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/JS/ListItem.tsx rename to app/client/src/ce/pages/AppIDE/components/JSListItem/ListItem.tsx index 2edc10d68940..6904e477c2fb 100644 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/ListItem.tsx +++ b/app/client/src/ce/pages/AppIDE/components/JSListItem/ListItem.tsx @@ -1,6 +1,6 @@ import React from "react"; import type { EntityItem } from "ee/IDE/Interfaces/EntityItem"; -import { JSEntityItem } from "pages/Editor/IDE/EditorPane/JS/EntityItem/JSEntityItem"; +import { JSEntityItem } from "pages/AppIDE/components/JSEntityItem"; export const JSEntity = (props: { item: EntityItem }) => { return ; diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/old/ListItem.tsx b/app/client/src/ce/pages/AppIDE/components/JSListItem/old/ListItem.tsx similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/JS/old/ListItem.tsx rename to app/client/src/ce/pages/AppIDE/components/JSListItem/old/ListItem.tsx diff --git a/app/client/src/ce/pages/AppIDE/components/LibrariesList/LibrarySidePane.tsx b/app/client/src/ce/pages/AppIDE/components/LibrariesList/LibrarySidePane.tsx new file mode 100644 index 000000000000..6a6eb00b1797 --- /dev/null +++ b/app/client/src/ce/pages/AppIDE/components/LibrariesList/LibrarySidePane.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import JSLibrariesSection from "pages/AppIDE/components/LibrariesList/JSLibrariesSection"; +import { IDESidePaneWrapper } from "IDE"; + +const LibrarySidePane = (props: { showAddButton?: boolean }) => { + const { showAddButton = true } = props; + + return ( + + + + ); +}; + +export default LibrarySidePane; diff --git a/app/client/src/ce/pages/AppIDE/components/MissingModuleNotification.tsx b/app/client/src/ce/pages/AppIDE/components/MissingModuleNotification.tsx new file mode 100644 index 000000000000..31a72945305a --- /dev/null +++ b/app/client/src/ce/pages/AppIDE/components/MissingModuleNotification.tsx @@ -0,0 +1,7 @@ +import type { ReactElement } from "react"; + +function MissingModuleNotification(): ReactElement | null { + return null; +} + +export default MissingModuleNotification; diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryUrl.test.ts b/app/client/src/ce/pages/AppIDE/components/QueryAdd/getQueryUrl.test.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryUrl.test.ts rename to app/client/src/ce/pages/AppIDE/components/QueryAdd/getQueryUrl.test.ts diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryUrl.ts b/app/client/src/ce/pages/AppIDE/components/QueryAdd/getQueryUrl.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryUrl.ts rename to app/client/src/ce/pages/AppIDE/components/QueryAdd/getQueryUrl.ts diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx b/app/client/src/ce/pages/AppIDE/components/QueryAdd/useGroupedAddQueryOperations.tsx similarity index 51% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx rename to app/client/src/ce/pages/AppIDE/components/QueryAdd/useGroupedAddQueryOperations.tsx index 34bcdc29ea8b..ffff528078e6 100644 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx +++ b/app/client/src/ce/pages/AppIDE/components/QueryAdd/useGroupedAddQueryOperations.tsx @@ -1,80 +1,82 @@ -import { lazy, Suspense, useCallback, useMemo } from "react"; -import React from "react"; -import history from "utils/history"; -import { useLocation } from "react-router"; -import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity"; -import { useDispatch, useSelector } from "react-redux"; -import { useFilteredFileOperations } from "components/editorComponents/GlobalSearch/GlobalSearchHooks"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; +import { useDispatch, useSelector } from "react-redux"; import { getCurrentPageId, getPagePermissions, } from "selectors/editorSelectors"; import { getHasCreateActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; -import type { ActionOperation } from "components/editorComponents/GlobalSearch/utils"; -import { SEARCH_ITEM_TYPES } from "components/editorComponents/GlobalSearch/utils"; -import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages"; -import { getQueryUrl } from "ee/pages/Editor/IDE/EditorPane/Query/utils/getQueryUrl"; +import { useFilteredFileOperations } from "components/editorComponents/GlobalSearch/GlobalSearchHooks"; +import { FocusEntity } from "navigation/FocusEntity"; import { - ADD_PATH, - API_EDITOR_ID_PATH, - BUILDER_CUSTOM_PATH, - BUILDER_PATH, - BUILDER_PATH_DEPRECATED, -} from "ee/constants/routes/appRoutes"; -import { SAAS_EDITOR_API_ID_PATH } from "pages/Editor/SaaSEditor/constants"; -import type { UseRoutes } from "IDE/Interfaces/UseRoutes"; + type ActionOperation, + SEARCH_ITEM_TYPES, +} from "components/editorComponents/GlobalSearch/utils"; +import type { GroupedAddOperations } from "IDE/Interfaces/GroupedAddOperations"; +import type { + EntityGroupProps, + EntityItemProps, + ListItemProps, +} from "@appsmith/ads"; +import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages"; import type { AppState } from "ee/reducers"; +import { useCallback, useMemo } from "react"; import keyBy from "lodash/keyBy"; +import { createAddClassName } from "pages/AppIDE/constants"; import { getPluginEntityIcon } from "pages/Editor/Explorer/ExplorerIcons"; -import { - type EntityGroupProps, - type ListItemProps, - type EntityItemProps, -} from "@appsmith/ads"; -import { createAddClassName } from "pages/Editor/IDE/EditorPane/utils"; -import { getIDEViewMode } from "selectors/ideSelectors"; -import { EditorViewMode } from "IDE/Interfaces/EditorTypes"; -import { setListViewActiveState } from "actions/ideActions"; -import { retryPromise } from "utils/AppsmithUtils"; -import Skeleton from "widgets/Skeleton"; -export const useQueryAdd = () => { - const location = useLocation(); +export const useAddQueryListItems = () => { const dispatch = useDispatch(); - const currentEntityInfo = identifyEntityFromPath(location.pathname); - const ideViewMode = useSelector(getIDEViewMode); + const pageId = useSelector(getCurrentPageId) as string; + const plugins = useSelector((state: AppState) => { + return state.entities.plugins.list; + }); + const pluginGroups = useMemo(() => keyBy(plugins, "id"), [plugins]); - const openAddQuery = useCallback(() => { - if (currentEntityInfo.entity === FocusEntity.QUERY_ADD) { - if (ideViewMode === EditorViewMode.SplitScreen) { - dispatch(setListViewActiveState(false)); + const onCreateItemClick = useCallback( + (item: ActionOperation) => { + if (item.action) { + dispatch(item.action(pageId, "ENTITY_EXPLORER")); + } else if (item.redirect) { + item.redirect(pageId, "ENTITY_EXPLORER"); } + }, + [pageId, dispatch], + ); - return; - } - - const url = getQueryUrl(currentEntityInfo); - - history.push(url); - }, [currentEntityInfo, dispatch, ideViewMode]); + const getListItems = (data: ActionOperation[]) => { + return data.map((fileOperation) => { + let title = + fileOperation.entityExplorerTitle || + fileOperation.dsName || + fileOperation.title; - const closeAddQuery = useCallback(() => { - const url = getQueryUrl(currentEntityInfo, false); + title = + fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE + ? fileOperation.title + : title; + const className = createAddClassName(title); + const icon = + fileOperation.icon || + (fileOperation.pluginId && + getPluginEntityIcon(pluginGroups[fileOperation.pluginId])); - history.push(url); - }, [currentEntityInfo]); + return { + startIcon: icon, + className: className, + title, + description: + fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE + ? fileOperation.dsName + : "", + descriptionType: "inline", + onClick: onCreateItemClick.bind(null, fileOperation), + } as ListItemProps; + }); + }; - return { openAddQuery, closeAddQuery }; + return { getListItems }; }; - -export type GroupedAddOperations = Array<{ - title?: string; - className: string; - operations: ActionOperation[]; -}>; - export const useGroupedAddQueryOperations = () => { const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); const pagePermissions = useSelector(getPagePermissions); @@ -144,133 +146,3 @@ export const useGroupedAddQueryOperations = () => { return groupedItems; }; - -const PluginActionEditor = lazy(async () => - retryPromise( - async () => - import( - /* webpackChunkName: "PluginActionEditor" */ "pages/Editor/AppPluginActionEditor" - ), - ), -); - -const AddQuery = lazy(async () => - retryPromise( - async () => - import( - /* webpackChunkName: "AddQuery" */ "pages/Editor/IDE/EditorPane/Query/Add" - ), - ), -); - -const QueryEmpty = lazy(async () => - retryPromise( - async () => - import( - /* webpackChunkName: "QueryEmpty" */ "../../../../../../PluginActionEditor/components/PluginActionForm/components/UQIEditor/QueriesBlankState" - ), - ), -); - -export const useQueryEditorRoutes = (path: string): UseRoutes => { - const skeleton = useMemo(() => , []); - - return useMemo( - () => [ - { - key: "AddQuery", - exact: true, - component: () => ( - - - - ), - path: [`${path}${ADD_PATH}`, `${path}/:baseQueryId${ADD_PATH}`], - }, - { - key: "PluginActionEditor", - component: () => { - return ( - - - - ); - }, - path: [ - BUILDER_PATH + API_EDITOR_ID_PATH, - BUILDER_CUSTOM_PATH + API_EDITOR_ID_PATH, - BUILDER_PATH_DEPRECATED + API_EDITOR_ID_PATH, - BUILDER_PATH + SAAS_EDITOR_API_ID_PATH, - BUILDER_CUSTOM_PATH + SAAS_EDITOR_API_ID_PATH, - BUILDER_PATH_DEPRECATED + SAAS_EDITOR_API_ID_PATH, - path + "/:baseQueryId", - ], - exact: true, - }, - { - key: "QueryEmpty", - component: () => ( - - - - ), - exact: true, - path: [path], - }, - ], - [path, skeleton], - ); -}; - -export const useAddQueryListItems = () => { - const dispatch = useDispatch(); - const pageId = useSelector(getCurrentPageId) as string; - const plugins = useSelector((state: AppState) => { - return state.entities.plugins.list; - }); - const pluginGroups = useMemo(() => keyBy(plugins, "id"), [plugins]); - - const onCreateItemClick = useCallback( - (item: ActionOperation) => { - if (item.action) { - dispatch(item.action(pageId, "ENTITY_EXPLORER")); - } else if (item.redirect) { - item.redirect(pageId, "ENTITY_EXPLORER"); - } - }, - [pageId, dispatch], - ); - - const getListItems = (data: ActionOperation[]) => { - return data.map((fileOperation) => { - let title = - fileOperation.entityExplorerTitle || - fileOperation.dsName || - fileOperation.title; - - title = - fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE - ? fileOperation.title - : title; - const className = createAddClassName(title); - const icon = - fileOperation.icon || - (fileOperation.pluginId && - getPluginEntityIcon(pluginGroups[fileOperation.pluginId])); - - return { - startIcon: icon, - className: className, - title, - description: - fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE - ? fileOperation.dsName - : "", - descriptionType: "inline", - onClick: onCreateItemClick.bind(null, fileOperation), - } as ListItemProps; - }); - }; - - return { getListItems }; -}; diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/ListItem.tsx b/app/client/src/ce/pages/AppIDE/components/QueryEntityItem/ListItem.tsx similarity index 67% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/Query/ListItem.tsx rename to app/client/src/ce/pages/AppIDE/components/QueryEntityItem/ListItem.tsx index f877949a889a..bfb22a902fbb 100644 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/ListItem.tsx +++ b/app/client/src/ce/pages/AppIDE/components/QueryEntityItem/ListItem.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { QueryEntityItem } from "pages/Editor/IDE/EditorPane/Query/EntityItem/QueryEntityItem"; +import { QueryEntityItem } from "pages/AppIDE/components/QueryEntityItem"; import type { EntityItem } from "ee/IDE/Interfaces/EntityItem"; export const ActionEntityItem = (props: { item: EntityItem }) => { diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/old/ListItem.tsx b/app/client/src/ce/pages/AppIDE/components/QueryEntityItem/old/ListItem.tsx similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/Query/old/ListItem.tsx rename to app/client/src/ce/pages/AppIDE/components/QueryEntityItem/old/ListItem.tsx diff --git a/app/client/src/ce/pages/Editor/IDE/constants/SidebarButtons.ts b/app/client/src/ce/pages/AppIDE/constants/SidebarButtons.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/constants/SidebarButtons.ts rename to app/client/src/ce/pages/AppIDE/constants/SidebarButtons.ts diff --git a/app/client/src/ce/pages/Editor/IDE/Header/useLibraryHeaderTitle.ts b/app/client/src/ce/pages/AppIDE/layout/components/Header/useLibraryHeaderTitle.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/Header/useLibraryHeaderTitle.ts rename to app/client/src/ce/pages/AppIDE/layout/components/Header/useLibraryHeaderTitle.ts diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/constants.ts b/app/client/src/ce/pages/AppIDE/layout/constants.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/constants.ts rename to app/client/src/ce/pages/AppIDE/layout/constants.ts diff --git a/app/client/src/ce/pages/AppIDE/layout/routers/JSEditor/constants.ts b/app/client/src/ce/pages/AppIDE/layout/routers/JSEditor/constants.ts new file mode 100644 index 000000000000..32e2793cd844 --- /dev/null +++ b/app/client/src/ce/pages/AppIDE/layout/routers/JSEditor/constants.ts @@ -0,0 +1,28 @@ +import type { UseRoutes } from "IDE/Interfaces/UseRoutes"; +import { ADD_PATH } from "ee/constants/routes/appRoutes"; +import AddJS from "pages/AppIDE/components/JSAdd/loader"; +import JSEditor from "pages/Editor/JSEditor/loader"; +import JSBlankState from "pages/Editor/JSEditor/JSBlankState"; + +export const JSEditorRoutes = (path: string): UseRoutes => { + return [ + { + exact: true, + key: "AddJS", + component: AddJS, + path: [`${path}${ADD_PATH}`, `${path}/:baseCollectionId${ADD_PATH}`], + }, + { + exact: true, + key: "JSEditor", + component: JSEditor, + path: [path + "/:baseCollectionId"], + }, + { + key: "JSEmpty", + component: JSBlankState, + exact: true, + path: [path], + }, + ]; +}; diff --git a/app/client/src/ce/pages/AppIDE/layout/routers/MainPane/constants.ts b/app/client/src/ce/pages/AppIDE/layout/routers/MainPane/constants.ts new file mode 100644 index 000000000000..33e26a766533 --- /dev/null +++ b/app/client/src/ce/pages/AppIDE/layout/routers/MainPane/constants.ts @@ -0,0 +1,103 @@ +import WidgetsEditor from "pages/Editor/WidgetsEditor"; +import { + ADD_PATH, + API_EDITOR_ID_ADD_PATH, + API_EDITOR_ID_PATH, + APP_LIBRARIES_EDITOR_PATH, + APP_PACKAGES_EDITOR_PATH, + APP_SETTINGS_EDITOR_PATH, + BUILDER_CHECKLIST_PATH, + BUILDER_CUSTOM_PATH, + BUILDER_PATH, + BUILDER_PATH_DEPRECATED, + DATA_SOURCES_EDITOR_ID_PATH, + DATA_SOURCES_EDITOR_LIST_PATH, + INTEGRATION_EDITOR_PATH, + JS_COLLECTION_EDITOR_PATH, + JS_COLLECTION_ID_PATH, + LIST_PATH, + QUERIES_EDITOR_BASE_PATH, + QUERIES_EDITOR_ID_ADD_PATH, + QUERIES_EDITOR_ID_PATH, + WIDGETS_EDITOR_BASE_PATH, + WIDGETS_EDITOR_ID_PATH, +} from "ee/constants/routes/appRoutes"; +import { + SAAS_EDITOR_API_ID_ADD_PATH, + SAAS_EDITOR_API_ID_PATH, + SAAS_EDITOR_DATASOURCE_ID_PATH, + SAAS_EDITOR_PATH, +} from "pages/Editor/SaaSEditor/constants"; +import CreateNewDatasourceTab from "pages/Editor/IntegrationEditor/CreateNewDatasourceTab"; +import { FirstTimeUserOnboardingChecklist } from "pages/Editor/FirstTimeUserOnboarding/loader"; +import DataSourceEditor from "pages/Editor/DataSourceEditor"; +import DatasourceBlankState from "pages/Editor/DataSourceEditor/DatasourceBlankState"; +import DatasourceForm from "pages/Editor/SaaSEditor/DatasourceForm"; + +export const MainPaneRoutes = (path: string) => [ + { + key: "Canvas", + component: WidgetsEditor, + exact: true, + path: [ + BUILDER_PATH_DEPRECATED, + BUILDER_PATH, + BUILDER_CUSTOM_PATH, + `${BUILDER_PATH_DEPRECATED}${ADD_PATH}`, + `${BUILDER_PATH}${ADD_PATH}`, + `${BUILDER_CUSTOM_PATH}${ADD_PATH}`, + `${path}${ADD_PATH}`, + `${path}${WIDGETS_EDITOR_BASE_PATH}`, + `${path}${WIDGETS_EDITOR_ID_PATH}`, + `${path}${WIDGETS_EDITOR_ID_PATH}${ADD_PATH}`, + `${path}${API_EDITOR_ID_PATH}`, + `${path}${API_EDITOR_ID_PATH}${LIST_PATH}`, + `${path}${API_EDITOR_ID_ADD_PATH}`, + `${path}${QUERIES_EDITOR_BASE_PATH}`, + `${path}${QUERIES_EDITOR_BASE_PATH}${ADD_PATH}`, + `${path}${QUERIES_EDITOR_ID_PATH}`, + `${path}${QUERIES_EDITOR_ID_ADD_PATH}`, + `${path}${QUERIES_EDITOR_ID_PATH}${LIST_PATH}`, + `${path}${JS_COLLECTION_EDITOR_PATH}`, + `${path}${JS_COLLECTION_EDITOR_PATH}${ADD_PATH}`, + `${path}${JS_COLLECTION_ID_PATH}`, + `${path}${JS_COLLECTION_ID_PATH}${LIST_PATH}`, + `${path}${SAAS_EDITOR_PATH}`, + `${path}${SAAS_EDITOR_API_ID_PATH}`, + `${path}${SAAS_EDITOR_API_ID_ADD_PATH}`, + `${path}${APP_LIBRARIES_EDITOR_PATH}`, + `${path}${APP_PACKAGES_EDITOR_PATH}`, + `${path}${APP_SETTINGS_EDITOR_PATH}`, + ], + }, + { + key: "Datasource Create and Active", + component: CreateNewDatasourceTab, + exact: true, + path: `${path}${INTEGRATION_EDITOR_PATH}`, + }, + { + key: "OnboardingChecklist", + component: FirstTimeUserOnboardingChecklist, + exact: true, + path: `${path}${BUILDER_CHECKLIST_PATH}`, + }, + { + key: "DatasourceEditor", + component: DataSourceEditor, + exact: true, + path: `${path}${DATA_SOURCES_EDITOR_ID_PATH}`, + }, + { + key: "DatasourceBlankState", + component: DatasourceBlankState, + exact: true, + path: `${path}${DATA_SOURCES_EDITOR_LIST_PATH}`, + }, + { + key: "SAASDatasourceEditor", + component: DatasourceForm, + exact: true, + path: `${path}${SAAS_EDITOR_DATASOURCE_ID_PATH}`, + }, +]; diff --git a/app/client/src/ce/pages/AppIDE/layout/routers/QueryEditor/constants.ts b/app/client/src/ce/pages/AppIDE/layout/routers/QueryEditor/constants.ts new file mode 100644 index 000000000000..79257525be9c --- /dev/null +++ b/app/client/src/ce/pages/AppIDE/layout/routers/QueryEditor/constants.ts @@ -0,0 +1,43 @@ +import type { UseRoutes } from "IDE/Interfaces/UseRoutes"; +import { + ADD_PATH, + API_EDITOR_ID_PATH, + BUILDER_CUSTOM_PATH, + BUILDER_PATH, + BUILDER_PATH_DEPRECATED, +} from "ee/constants/routes/appRoutes"; +import { SAAS_EDITOR_API_ID_PATH } from "pages/Editor/SaaSEditor/constants"; +import PluginActionEditor from "pages/AppIDE/components/AppPluginActionEditor/loader"; +import QueryAdd from "pages/AppIDE/components/QueryAdd/loader"; +import QueriesBlankState from "PluginActionEditor/components/PluginActionForm/components/UQIEditor/QueriesBlankState"; + +export const QueryEditorRoutes = (path: string): UseRoutes => { + return [ + { + key: "QueryAdd", + exact: true, + component: QueryAdd, + path: [`${path}${ADD_PATH}`, `${path}/:baseQueryId${ADD_PATH}`], + }, + { + key: "PluginActionEditor", + component: PluginActionEditor, + path: [ + BUILDER_PATH + API_EDITOR_ID_PATH, + BUILDER_CUSTOM_PATH + API_EDITOR_ID_PATH, + BUILDER_PATH_DEPRECATED + API_EDITOR_ID_PATH, + BUILDER_PATH + SAAS_EDITOR_API_ID_PATH, + BUILDER_CUSTOM_PATH + SAAS_EDITOR_API_ID_PATH, + BUILDER_PATH_DEPRECATED + SAAS_EDITOR_API_ID_PATH, + path + "/:baseQueryId", + ], + exact: true, + }, + { + key: "QueryEmpty", + component: QueriesBlankState, + exact: true, + path: [path], + }, + ]; +}; diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSEntityItemUrl.test.ts b/app/client/src/ce/pages/AppIDE/layout/routers/utils/getJSEntityItemUrl.test.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSEntityItemUrl.test.ts rename to app/client/src/ce/pages/AppIDE/layout/routers/utils/getJSEntityItemUrl.test.ts diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSEntityItemUrl.ts b/app/client/src/ce/pages/AppIDE/layout/routers/utils/getJSEntityItemUrl.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSEntityItemUrl.ts rename to app/client/src/ce/pages/AppIDE/layout/routers/utils/getJSEntityItemUrl.ts diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryEntityItemUrl.test.ts b/app/client/src/ce/pages/AppIDE/layout/routers/utils/getQueryEntityItemUrl.test.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryEntityItemUrl.test.ts rename to app/client/src/ce/pages/AppIDE/layout/routers/utils/getQueryEntityItemUrl.test.ts diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryEntityItemUrl.ts b/app/client/src/ce/pages/AppIDE/layout/routers/utils/getQueryEntityItemUrl.ts similarity index 100% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryEntityItemUrl.ts rename to app/client/src/ce/pages/AppIDE/layout/routers/utils/getQueryEntityItemUrl.ts diff --git a/app/client/src/ce/pages/AppViewer/KnowledgeBase/KBViewerFloatingButton.tsx b/app/client/src/ce/pages/AppViewer/KnowledgeBase/KBViewerFloatingButton.tsx deleted file mode 100644 index a4578943a59c..000000000000 --- a/app/client/src/ce/pages/AppViewer/KnowledgeBase/KBViewerFloatingButton.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const KBViewerFloatingButton = () => { - return null; -}; diff --git a/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx b/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx index 06940dc36fcc..b80fdc7c7bc2 100644 --- a/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx +++ b/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx @@ -15,8 +15,8 @@ jest.mock("selectors/gitModSelectors", () => ({ const defaultStoreState = { ...unitTestBaseMockStore, - tenant: { - tenantConfiguration: {}, + organization: { + organizationConfiguration: {}, }, entities: { ...unitTestBaseMockStore.entities, diff --git a/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx b/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx index 465c87898aca..c306a5396e31 100644 --- a/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx +++ b/app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx @@ -27,7 +27,7 @@ import { fetchMockDatasources } from "actions/datasourceActions"; import DatasourceForm from "pages/Editor/SaaSEditor/DatasourceForm"; import type { Datasource } from "entities/Datasource"; import { fetchingEnvironmentConfigs } from "ee/actions/environmentAction"; -import { shouldShowLicenseBanner } from "ee/selectors/tenantSelectors"; +import { shouldShowLicenseBanner } from "ee/selectors/organizationSelectors"; import { isAirgapped } from "ee/utils/airgapHelpers"; const SectionWrapper = styled.div<{ isBannerVisible: boolean }>` diff --git a/app/client/src/ce/pages/Applications/index.tsx b/app/client/src/ce/pages/Applications/index.tsx index 393c3530e9bb..f04d3e39e388 100644 --- a/app/client/src/ce/pages/Applications/index.tsx +++ b/app/client/src/ce/pages/Applications/index.tsx @@ -97,9 +97,9 @@ import { getIsFetchingApplications, } from "ee/selectors/selectedWorkspaceSelectors"; import { - getTenantPermissions, + getOrganizationPermissions, shouldShowLicenseBanner, -} from "ee/selectors/tenantSelectors"; +} from "ee/selectors/organizationSelectors"; import { getWorkflowsList } from "ee/selectors/workflowSelectors"; import { getFetchedWorkspaces, @@ -301,12 +301,12 @@ export function LeftPaneSection(props: { }) { const dispatch = useDispatch(); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); - const tenantPermissions = useSelector(getTenantPermissions); + const organizationPermissions = useSelector(getOrganizationPermissions); const fetchedWorkspaces = useSelector(getFetchedWorkspaces); const canCreateWorkspace = getHasCreateWorkspacePermission( isFeatureEnabled, - tenantPermissions, + organizationPermissions, ); const createNewWorkspace = async () => { diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.tsx b/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.tsx deleted file mode 100644 index fbc198f2bd61..000000000000 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { lazy, Suspense, useCallback, useMemo } from "react"; -import React from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { createNewJSCollection } from "actions/jsPaneActions"; -import { getCurrentPageId } from "selectors/editorSelectors"; -import type { GroupedAddOperations } from "ee/pages/Editor/IDE/EditorPane/Query/hooks"; -import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages"; -import { JsFileIconV2 } from "pages/Editor/Explorer/ExplorerIcons"; -import { SEARCH_ITEM_TYPES } from "components/editorComponents/GlobalSearch/utils"; -import type { UseRoutes } from "IDE/Interfaces/UseRoutes"; -import { ADD_PATH } from "ee/constants/routes/appRoutes"; -import history from "utils/history"; -import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity"; -import { useModuleOptions } from "ee/utils/moduleInstanceHelpers"; -import { getJSUrl } from "ee/pages/Editor/IDE/EditorPane/JS/utils/getJSUrl"; -import { getIDEViewMode } from "selectors/ideSelectors"; -import { EditorViewMode } from "IDE/Interfaces/EditorTypes"; -import { setListViewActiveState } from "actions/ideActions"; -import { retryPromise } from "utils/AppsmithUtils"; -import Skeleton from "widgets/Skeleton"; - -export const useJSAdd = () => { - const pageId = useSelector(getCurrentPageId); - const dispatch = useDispatch(); - const currentEntityInfo = identifyEntityFromPath(location.pathname); - const moduleCreationOptions = useModuleOptions(); - const jsModuleCreationOptions = moduleCreationOptions.filter( - (opt) => opt.focusEntityType === FocusEntity.JS_MODULE_INSTANCE, - ); - const ideViewMode = useSelector(getIDEViewMode); - - const openAddJS = useCallback(() => { - if (jsModuleCreationOptions.length === 0) { - dispatch(createNewJSCollection(pageId, "ENTITY_EXPLORER")); - } else { - if (currentEntityInfo.entity === FocusEntity.JS_OBJECT_ADD) { - if (ideViewMode === EditorViewMode.SplitScreen) { - dispatch(setListViewActiveState(false)); - } - - return; - } - - const url = getJSUrl(currentEntityInfo, true); - - history.push(url); - } - }, [ - jsModuleCreationOptions, - pageId, - dispatch, - currentEntityInfo, - ideViewMode, - ]); - - const closeAddJS = useCallback(() => { - const url = getJSUrl(currentEntityInfo, false); - - history.push(url); - }, [currentEntityInfo]); - - return { openAddJS, closeAddJS }; -}; - -export const useIsJSAddLoading = () => { - const moduleCreationOptions = useModuleOptions(); - const jsModuleCreationOptions = moduleCreationOptions.filter( - (opt) => opt.focusEntityType === FocusEntity.JS_MODULE_INSTANCE, - ); - const { isCreating } = useSelector((state) => state.ui.jsPane); - - if (jsModuleCreationOptions.length === 0) { - return isCreating; - } - - return false; -}; - -export const useGroupedAddJsOperations = (): GroupedAddOperations => { - return [ - { - className: "t--blank-js", - operations: [ - { - title: createMessage(EDITOR_PANE_TEXTS.js_blank_object_item), - desc: "", - icon: JsFileIconV2(16, 16), - kind: SEARCH_ITEM_TYPES.actionOperation, - action: (pageId) => createNewJSCollection(pageId, "ENTITY_EXPLORER"), - }, - ], - }, - ]; -}; - -const AddJS = lazy(async () => - retryPromise( - async () => - import( - /* webpackChunkName: "AddJS" */ "pages/Editor/IDE/EditorPane/JS/Add" - ), - ), -); -const JSEditor = lazy(async () => - retryPromise( - async () => - import(/* webpackChunkName: "JSEditor" */ "pages/Editor/JSEditor"), - ), -); - -const JSEmpty = lazy(async () => - retryPromise( - async () => - import( - /* webpackChunkName: "JSEmpty" */ "pages/Editor/JSEditor/JSBlankState" - ), - ), -); - -export const useJSEditorRoutes = (path: string): UseRoutes => { - return useMemo( - () => [ - { - exact: true, - key: "AddJS", - component: (args) => ( - }> - - - ), - path: [`${path}${ADD_PATH}`, `${path}/:baseCollectionId${ADD_PATH}`], - }, - { - exact: true, - key: "JSEditor", - component: (args) => ( - }> - - - ), - path: [path + "/:baseCollectionId"], - }, - { - key: "JSEmpty", - component: (args) => ( - }> - - - ), - exact: true, - path: [path], - }, - ], - [path], - ); -}; diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSContextMenuByIdeType.tsx b/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSContextMenuByIdeType.tsx deleted file mode 100644 index 5590b59650a8..000000000000 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/utils/getJSContextMenuByIdeType.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react"; -import { IDE_TYPE, type IDEType } from "ee/IDE/Interfaces/IDETypes"; -import EntityContextMenu from "pages/Editor/IDE/EditorPane/components/EntityContextMenu"; -import { AppJSContextMenuItems } from "pages/Editor/IDE/EditorPane/JS/EntityItem/AppJSContextMenuItems"; -import type { JSCollection } from "entities/JSCollection"; - -export const getJSContextMenuByIdeType = ( - ideType: IDEType, - jsAction: JSCollection, -) => { - switch (ideType) { - case IDE_TYPE.App: { - return ( - - - - ); - } - } -}; diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryContextMenuByIdeType.tsx b/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryContextMenuByIdeType.tsx deleted file mode 100644 index 179e6a3fb863..000000000000 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/utils/getQueryContextMenuByIdeType.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react"; -import { IDE_TYPE, type IDEType } from "ee/IDE/Interfaces/IDETypes"; -import type { Action } from "entities/Action"; -import { AppQueryContextMenuItems } from "pages/Editor/IDE/EditorPane/Query/EntityItem/AppQueryContextMenuItems"; -import EntityContextMenu from "pages/Editor/IDE/EditorPane/components/EntityContextMenu"; - -export const getQueryContextMenuByIdeType = ( - ideType: IDEType, - action: Action, -) => { - switch (ideType) { - case IDE_TYPE.App: { - return ( - - - - ); - } - } -}; diff --git a/app/client/src/ce/pages/Editor/IDE/LeftPane/LibrarySidePane.tsx b/app/client/src/ce/pages/Editor/IDE/LeftPane/LibrarySidePane.tsx deleted file mode 100644 index 3203c1b5b64e..000000000000 --- a/app/client/src/ce/pages/Editor/IDE/LeftPane/LibrarySidePane.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from "react"; -import JSLibrariesSection from "pages/Editor/IDE/LeftPane/JSLibrariesSection"; -import { IDESidePaneWrapper } from "IDE"; - -const LibrarySidePane = () => { - return ( - - - - ); -}; - -export default LibrarySidePane; diff --git a/app/client/src/ce/pages/Editor/IDE/MainPane/useMissingModuleNotification.tsx b/app/client/src/ce/pages/Editor/IDE/MainPane/useMissingModuleNotification.tsx deleted file mode 100644 index 4fc0a154f515..000000000000 --- a/app/client/src/ce/pages/Editor/IDE/MainPane/useMissingModuleNotification.tsx +++ /dev/null @@ -1,5 +0,0 @@ -function useMissingModuleNotification(): React.ReactNode | null { - return null; -} - -export default useMissingModuleNotification; diff --git a/app/client/src/ce/pages/Editor/IDE/MainPane/useRoutes.tsx b/app/client/src/ce/pages/Editor/IDE/MainPane/useRoutes.tsx deleted file mode 100644 index 8f16afc63327..000000000000 --- a/app/client/src/ce/pages/Editor/IDE/MainPane/useRoutes.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import WidgetsEditor from "pages/Editor/WidgetsEditor"; -import { - ADD_PATH, - API_EDITOR_ID_ADD_PATH, - API_EDITOR_ID_PATH, - APP_LIBRARIES_EDITOR_PATH, - APP_PACKAGES_EDITOR_PATH, - APP_SETTINGS_EDITOR_PATH, - BUILDER_CHECKLIST_PATH, - BUILDER_CUSTOM_PATH, - BUILDER_PATH, - BUILDER_PATH_DEPRECATED, - DATA_SOURCES_EDITOR_ID_PATH, - DATA_SOURCES_EDITOR_LIST_PATH, - INTEGRATION_EDITOR_PATH, - JS_COLLECTION_EDITOR_PATH, - JS_COLLECTION_ID_PATH, - LIST_PATH, - QUERIES_EDITOR_BASE_PATH, - QUERIES_EDITOR_ID_ADD_PATH, - QUERIES_EDITOR_ID_PATH, - WIDGETS_EDITOR_BASE_PATH, - WIDGETS_EDITOR_ID_PATH, -} from "constants/routes"; -import CreateNewDatasourceTab from "pages/Editor/IntegrationEditor/CreateNewDatasourceTab"; -import { - SAAS_EDITOR_API_ID_ADD_PATH, - SAAS_EDITOR_API_ID_PATH, - SAAS_EDITOR_DATASOURCE_ID_PATH, - SAAS_EDITOR_PATH, -} from "pages/Editor/SaaSEditor/constants"; -import DatasourceForm from "pages/Editor/SaaSEditor/DatasourceForm"; -import DataSourceEditor from "pages/Editor/DataSourceEditor"; -import DatasourceBlankState from "pages/Editor/DataSourceEditor/DatasourceBlankState"; -import type { RouteProps } from "react-router"; -import { useSelector } from "react-redux"; -import { lazy, Suspense } from "react"; -import React from "react"; - -import { retryPromise } from "utils/AppsmithUtils"; -import Skeleton from "widgets/Skeleton"; -import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; - -const FirstTimeUserOnboardingChecklist = lazy(async () => - retryPromise( - async () => - import( - /* webpackChunkName: "FirstTimeUserOnboardingChecklist" */ "pages/Editor/FirstTimeUserOnboarding/Checklist" - ), - ), -); - -export const LazilyLoadedFirstTimeUserOnboardingChecklist = () => { - return ( - }> - - - ); -}; -export interface RouteReturnType extends RouteProps { - key: string; -} - -/** - * The hook is extended in EE, please be mindful when modifying the - * signature; it might break the implementation in EE. - */ - -function useRoutes(path: string): RouteReturnType[] { - const isPreviewMode = useSelector(selectCombinedPreviewMode); - - return [ - { - key: "Canvas", - component: WidgetsEditor, - exact: true, - path: [ - BUILDER_PATH_DEPRECATED, - BUILDER_PATH, - BUILDER_CUSTOM_PATH, - `${BUILDER_PATH_DEPRECATED}${ADD_PATH}`, - `${BUILDER_PATH}${ADD_PATH}`, - `${BUILDER_CUSTOM_PATH}${ADD_PATH}`, - `${path}${ADD_PATH}`, - `${path}${WIDGETS_EDITOR_BASE_PATH}`, - `${path}${WIDGETS_EDITOR_ID_PATH}`, - `${path}${WIDGETS_EDITOR_ID_PATH}${ADD_PATH}`, - `${path}${API_EDITOR_ID_PATH}`, - `${path}${API_EDITOR_ID_PATH}${LIST_PATH}`, - `${path}${API_EDITOR_ID_ADD_PATH}`, - `${path}${QUERIES_EDITOR_BASE_PATH}`, - `${path}${QUERIES_EDITOR_BASE_PATH}${ADD_PATH}`, - `${path}${QUERIES_EDITOR_ID_PATH}`, - `${path}${QUERIES_EDITOR_ID_ADD_PATH}`, - `${path}${QUERIES_EDITOR_ID_PATH}${LIST_PATH}`, - `${path}${JS_COLLECTION_EDITOR_PATH}`, - `${path}${JS_COLLECTION_EDITOR_PATH}${ADD_PATH}`, - `${path}${JS_COLLECTION_ID_PATH}`, - `${path}${JS_COLLECTION_ID_PATH}${LIST_PATH}`, - `${path}${SAAS_EDITOR_PATH}`, - `${path}${SAAS_EDITOR_API_ID_PATH}`, - `${path}${SAAS_EDITOR_API_ID_ADD_PATH}`, - `${path}${APP_LIBRARIES_EDITOR_PATH}`, - `${path}${APP_PACKAGES_EDITOR_PATH}`, - `${path}${APP_SETTINGS_EDITOR_PATH}`, - ], - }, - { - key: "Datasource Create and Active", - component: isPreviewMode ? WidgetsEditor : CreateNewDatasourceTab, - exact: true, - path: `${path}${INTEGRATION_EDITOR_PATH}`, - }, - { - key: "OnboardingChecklist", - component: isPreviewMode - ? WidgetsEditor - : FirstTimeUserOnboardingChecklist, - exact: true, - path: `${path}${BUILDER_CHECKLIST_PATH}`, - }, - { - key: "DatasourceEditor", - component: isPreviewMode ? WidgetsEditor : DataSourceEditor, - exact: true, - path: `${path}${DATA_SOURCES_EDITOR_ID_PATH}`, - }, - { - key: "DatasourceBlankState", - component: isPreviewMode ? WidgetsEditor : DatasourceBlankState, - exact: true, - path: `${path}${DATA_SOURCES_EDITOR_LIST_PATH}`, - }, - { - key: "SAASDatasourceEditor", - component: isPreviewMode ? WidgetsEditor : DatasourceForm, - exact: true, - path: `${path}${SAAS_EDITOR_DATASOURCE_ID_PATH}`, - }, - ]; -} - -export default useRoutes; diff --git a/app/client/src/ce/pages/common/AppHeader.tsx b/app/client/src/ce/pages/common/AppHeader.tsx index cb28ed36871d..c85696568649 100644 --- a/app/client/src/ce/pages/common/AppHeader.tsx +++ b/app/client/src/ce/pages/common/AppHeader.tsx @@ -19,7 +19,7 @@ import { } from "constants/routes"; import Navigation from "pages/AppViewer/Navigation"; import type { RouteComponentProps } from "react-router"; -import { Header as AppIDEHeader } from "pages/Editor/IDE/Header"; +import { Header as AppIDEHeader } from "pages/AppIDE/layouts/components/Header"; export type Props = RouteComponentProps; diff --git a/app/client/src/reducers/entityReducers/canvasWidgetsReducer.test.ts b/app/client/src/ce/reducers/entityReducers/canvasWidgetsReducer.test.ts similarity index 100% rename from app/client/src/reducers/entityReducers/canvasWidgetsReducer.test.ts rename to app/client/src/ce/reducers/entityReducers/canvasWidgetsReducer.test.ts diff --git a/app/client/src/reducers/entityReducers/canvasWidgetsReducer.ts b/app/client/src/ce/reducers/entityReducers/canvasWidgetsReducer.ts similarity index 96% rename from app/client/src/reducers/entityReducers/canvasWidgetsReducer.ts rename to app/client/src/ce/reducers/entityReducers/canvasWidgetsReducer.ts index ccebf9e51b9b..e11c5e4d2aa4 100644 --- a/app/client/src/reducers/entityReducers/canvasWidgetsReducer.ts +++ b/app/client/src/ce/reducers/entityReducers/canvasWidgetsReducer.ts @@ -11,7 +11,7 @@ import { } from "utils/WidgetSizeUtils"; import { klona } from "klona"; import type { UpdateCanvasPayload } from "actions/pageActions"; -import type { SetWidgetDynamicPropertyPayload } from "../../actions/controlActions"; +import type { SetWidgetDynamicPropertyPayload } from "../../../actions/controlActions"; /* This type is an object whose keys are widgetIds and values are arrays with property paths and property values @@ -54,7 +54,7 @@ function getUpdatedWidgetLists( ); } -const canvasWidgetsReducer = createImmerReducer(initialState, { +export const handlers = { [ReduxActionTypes.INIT_CANVAS_LAYOUT]: ( state: CanvasWidgetsReduxState, action: ReduxAction, @@ -166,10 +166,12 @@ const canvasWidgetsReducer = createImmerReducer(initialState, { return state; }, -}); +}; export interface CanvasWidgetsReduxState { [widgetId: string]: FlattenedWidgetProps; } +const canvasWidgetsReducer = createImmerReducer(initialState, handlers); + export default canvasWidgetsReducer; diff --git a/app/client/src/reducers/entityReducers/canvasWidgetsStructureReducer.ts b/app/client/src/ce/reducers/entityReducers/canvasWidgetsStructureReducer.ts similarity index 89% rename from app/client/src/reducers/entityReducers/canvasWidgetsStructureReducer.ts rename to app/client/src/ce/reducers/entityReducers/canvasWidgetsStructureReducer.ts index cf0d1bcaa565..384701f9aea6 100644 --- a/app/client/src/reducers/entityReducers/canvasWidgetsStructureReducer.ts +++ b/app/client/src/ce/reducers/entityReducers/canvasWidgetsStructureReducer.ts @@ -24,14 +24,14 @@ export interface CanvasWidgetsStructureReduxState { topRow: number; } -const initialState: CanvasWidgetsStructureReduxState = { +export const initialState: CanvasWidgetsStructureReduxState = { type: "CANVAS_WIDGET", widgetId: MAIN_CONTAINER_WIDGET_ID, topRow: 0, bottomRow: CANVAS_DEFAULT_MIN_ROWS, }; -const canvasWidgetsStructureReducer = createImmerReducer(initialState, { +export const handlers = { [ReduxActionTypes.INIT_CANVAS_LAYOUT]: ( state: CanvasWidgetsStructureReduxState, action: ReduxAction, @@ -47,6 +47,11 @@ const canvasWidgetsStructureReducer = createImmerReducer(initialState, { [ReduxActionTypes.RESET_EDITOR_REQUEST]: () => { return klona(initialState); }, -}); +}; + +const canvasWidgetsStructureReducer = createImmerReducer( + initialState, + handlers, +); export default canvasWidgetsStructureReducer; diff --git a/app/client/src/ce/reducers/entityReducers/index.ts b/app/client/src/ce/reducers/entityReducers/index.ts index 7ca2fd5d3322..883f2e8ab9b8 100644 --- a/app/client/src/ce/reducers/entityReducers/index.ts +++ b/app/client/src/ce/reducers/entityReducers/index.ts @@ -1,7 +1,7 @@ import actionsReducer from "ee/reducers/entityReducers/actionsReducer"; import appReducer from "reducers/entityReducers/appReducer"; -import canvasWidgetsReducer from "reducers/entityReducers/canvasWidgetsReducer"; -import canvasWidgetsStructureReducer from "reducers/entityReducers/canvasWidgetsStructureReducer"; +import canvasWidgetsReducer from "ee/reducers/entityReducers/canvasWidgetsReducer"; +import canvasWidgetsStructureReducer from "ee/reducers/entityReducers/canvasWidgetsStructureReducer"; import metaWidgetsReducer from "reducers/entityReducers/metaWidgetsReducer"; import datasourceReducer from "reducers/entityReducers/datasourceReducer"; import jsActionsReducer from "ee/reducers/entityReducers/jsActionsReducer"; diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index e1339f84721f..e7537b9e557a 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -2,7 +2,7 @@ import entityReducer from "ee/reducers/entityReducers"; import uiReducer from "ee/reducers/uiReducers"; import evaluationsReducer from "reducers/evaluationReducers"; import { reducer as formReducer } from "redux-form"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { EditorReduxState } from "ee/reducers/uiReducers/editorReducer"; import type { ErrorReduxState } from "reducers/uiReducers/errorReducer"; import type { ActionDataState } from "ee/reducers/entityReducers/actionsReducer"; @@ -54,8 +54,8 @@ import SettingsReducer from "ee/reducers/settingsReducer"; import type { TriggerValuesEvaluationState } from "reducers/evaluationReducers/triggerReducer"; import type { CanvasWidgetStructure } from "WidgetProvider/constants"; import type { AppSettingsPaneReduxState } from "reducers/uiReducers/appSettingsPaneReducer"; -import type { TenantReduxState } from "ee/reducers/tenantReducer"; -import tenantReducer from "ee/reducers/tenantReducer"; +import type { OrganizationReduxState } from "ee/reducers/organizationReducer"; +import organizationReducer from "ee/reducers/organizationReducer"; import type { FocusHistoryState } from "reducers/uiReducers/focusHistoryReducer"; import type { EditorContextState } from "ee/reducers/uiReducers/editorContextReducer"; import type { LibraryState } from "reducers/uiReducers/libraryReducer"; @@ -78,7 +78,10 @@ import type { ActiveField } from "reducers/uiReducers/activeFieldEditorReducer"; import type { SelectedWorkspaceReduxState } from "ee/reducers/uiReducers/selectedWorkspaceReducer"; import type { ConsolidatedPageLoadState } from "reducers/uiReducers/consolidatedPageLoadReducer"; import type { BuildingBlocksReduxState } from "reducers/uiReducers/buildingBlockReducer"; -import type { GitArtifactRootReduxState, GitGlobalReduxState } from "git"; +import type { + GitArtifactRootReduxState, + GitGlobalReduxState, +} from "git/store/types"; import { gitReducer } from "git/store"; export const reducerObject = { @@ -87,7 +90,7 @@ export const reducerObject = { evaluations: evaluationsReducer, form: formReducer, settings: SettingsReducer, - tenant: tenantReducer, + organization: organizationReducer, linting: lintErrorReducer, git: gitReducer, }; @@ -180,7 +183,7 @@ export interface AppState { settings: SettingsReduxState; // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - tenant: TenantReduxState; + organization: OrganizationReduxState; git: { global: GitGlobalReduxState; artifacts: GitArtifactRootReduxState; diff --git a/app/client/src/ce/reducers/tenantReducer.ts b/app/client/src/ce/reducers/organizationReducer.ts similarity index 68% rename from app/client/src/ce/reducers/tenantReducer.ts rename to app/client/src/ce/reducers/organizationReducer.ts index d0abcdaaa06b..c53179aec271 100644 --- a/app/client/src/ce/reducers/tenantReducer.ts +++ b/app/client/src/ce/reducers/organizationReducer.ts @@ -11,9 +11,9 @@ import { } from "utils/BrandingUtils"; import { createReducer } from "utils/ReducerUtils"; -export interface TenantReduxState { +export interface OrganizationReduxState { userPermissions: string[]; - tenantConfiguration: Record; + organizationConfiguration: Record; new: boolean; isLoading: boolean; instanceId: string; @@ -29,9 +29,9 @@ export const defaultBrandingConfig = { // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const initialState: TenantReduxState = { +export const initialState: OrganizationReduxState = { userPermissions: [], - tenantConfiguration: { + organizationConfiguration: { ...defaultBrandingConfig, }, new: false, @@ -40,65 +40,65 @@ export const initialState: TenantReduxState = { }; export const handlers = { - [ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG]: ( + [ReduxActionTypes.FETCH_CURRENT_ORGANIZATION_CONFIG]: ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: TenantReduxState, + state: OrganizationReduxState, action: ReduxAction<{ isBackgroundRequest: boolean }>, ) => ({ ...state, isLoading: !action.payload.isBackgroundRequest, }), - [ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG_SUCCESS]: ( + [ReduxActionTypes.FETCH_CURRENT_ORGANIZATION_CONFIG_SUCCESS]: ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: TenantReduxState, + state: OrganizationReduxState, // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - action: ReduxAction>, + action: ReduxAction>, ) => ({ ...state, userPermissions: action.payload.userPermissions || [], - tenantConfiguration: { + organizationConfiguration: { ...defaultBrandingConfig, - ...state.tenantConfiguration, - ...action.payload.tenantConfiguration, + ...state.organizationConfiguration, + ...action.payload.organizationConfiguration, brandColors: { ...defaultBrandingConfig.brandColors, - ...action.payload.tenantConfiguration.brandColors, + ...action.payload.organizationConfiguration.brandColors, }, }, isLoading: false, instanceId: action.payload.instanceId, }), - [ReduxActionErrorTypes.FETCH_CURRENT_TENANT_CONFIG_ERROR]: ( + [ReduxActionErrorTypes.FETCH_CURRENT_ORGANIZATION_CONFIG_ERROR]: ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: TenantReduxState, + state: OrganizationReduxState, ) => ({ ...state, isLoading: false, }), - [ReduxActionTypes.UPDATE_TENANT_CONFIG_SUCCESS]: ( + [ReduxActionTypes.UPDATE_ORGANIZATION_CONFIG_SUCCESS]: ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: TenantReduxState, + state: OrganizationReduxState, // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - action: ReduxAction>, + action: ReduxAction>, ) => ({ ...state, ...action.payload, - tenantConfiguration: { - ...state.tenantConfiguration, - ...action.payload.tenantConfiguration, + organizationConfiguration: { + ...state.organizationConfiguration, + ...action.payload.organizationConfiguration, }, isLoading: false, }), - [ReduxActionErrorTypes.UPDATE_TENANT_CONFIG_ERROR]: ( + [ReduxActionErrorTypes.UPDATE_ORGANIZATION_CONFIG_ERROR]: ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: TenantReduxState, + state: OrganizationReduxState, ) => ({ ...state, isLoading: false, diff --git a/app/client/src/ce/reducers/settingsReducer.ts b/app/client/src/ce/reducers/settingsReducer.ts index b9354d99c8c5..db3164de752e 100644 --- a/app/client/src/ce/reducers/settingsReducer.ts +++ b/app/client/src/ce/reducers/settingsReducer.ts @@ -4,8 +4,8 @@ import { ReduxActionTypes, } from "ee/constants/ReduxActionConstants"; import { createReducer } from "utils/ReducerUtils"; -import type { TenantReduxState } from "ee/reducers/tenantReducer"; -import { tenantConfigConnection } from "ee/constants/tenantConstants"; +import type { OrganizationReduxState } from "ee/reducers/organizationReducer"; +import { organizationConfigConnection } from "ee/constants/organizationConstants"; export const initialState: SettingsReduxState = { isLoading: true, @@ -43,21 +43,21 @@ export const handlers = { ...action.payload, }, }), - [ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG_SUCCESS]: ( + [ReduxActionTypes.FETCH_CURRENT_ORGANIZATION_CONFIG_SUCCESS]: ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: SettingsReduxState & TenantReduxState, + state: SettingsReduxState & OrganizationReduxState, // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - action: ReduxAction>, + action: ReduxAction>, ) => { // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any const configs: any = {}; - tenantConfigConnection.forEach((key: string) => { - if (action.payload?.tenantConfiguration?.hasOwnProperty(key)) { - configs[key] = action.payload?.tenantConfiguration?.[key]; + organizationConfigConnection.forEach((key: string) => { + if (action.payload?.organizationConfiguration?.hasOwnProperty(key)) { + configs[key] = action.payload?.organizationConfiguration?.[key]; } }); @@ -70,21 +70,21 @@ export const handlers = { }, }; }, - [ReduxActionTypes.UPDATE_TENANT_CONFIG_SUCCESS]: ( + [ReduxActionTypes.UPDATE_ORGANIZATION_CONFIG_SUCCESS]: ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: SettingsReduxState & TenantReduxState, + state: SettingsReduxState & OrganizationReduxState, // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any - action: ReduxAction>, + action: ReduxAction>, ) => { // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any const configs: any = {}; - tenantConfigConnection.forEach((key: string) => { - if (action.payload?.tenantConfiguration?.hasOwnProperty(key)) { - configs[key] = action.payload?.tenantConfiguration?.[key]; + organizationConfigConnection.forEach((key: string) => { + if (action.payload?.organizationConfiguration?.hasOwnProperty(key)) { + configs[key] = action.payload?.organizationConfiguration?.[key]; } }); diff --git a/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx b/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx index eaf285c6fe9e..50c563673f74 100644 --- a/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx +++ b/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx @@ -25,8 +25,6 @@ import { import { create } from "mutative"; import { isEmpty } from "lodash"; import type { ApplicationPayload } from "entities/Application"; -import { gitConnectSuccess, type GitConnectSuccessPayload } from "git"; -import type { PayloadAction } from "@reduxjs/toolkit"; export const initialState: ApplicationsReduxState = { isSavingAppName: false, @@ -746,20 +744,6 @@ export const handlers = { isSavingNavigationSetting: false, }; }, - // git - [gitConnectSuccess.type]: ( - state: ApplicationsReduxState, - action: PayloadAction, - ) => { - return { - ...state, - currentApplication: { - ...state.currentApplication, - gitApplicationMetadata: - action.payload.responseData.gitApplicationMetadata, - }, - }; - }, }; const applicationsReducer = createReducer(initialState, handlers); diff --git a/app/client/src/ce/sagas/JSActionSagas.ts b/app/client/src/ce/sagas/JSActionSagas.ts index 5302d4c06c36..c9131722081a 100644 --- a/app/client/src/ce/sagas/JSActionSagas.ts +++ b/app/client/src/ce/sagas/JSActionSagas.ts @@ -67,7 +67,7 @@ import { } from "sagas/helper"; import { toast } from "@appsmith/ads"; import { updateAndSaveLayout } from "actions/pageActions"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { getWidgets } from "sagas/selectors"; import FocusRetention from "sagas/FocusRetentionSaga"; import { handleJSEntityRedirect } from "sagas/IDESaga"; diff --git a/app/client/src/ce/sagas/PageSagas.tsx b/app/client/src/ce/sagas/PageSagas.tsx index de16549df766..53481cfcc892 100644 --- a/app/client/src/ce/sagas/PageSagas.tsx +++ b/app/client/src/ce/sagas/PageSagas.tsx @@ -60,7 +60,7 @@ import PageApi from "api/PageApi"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, put, select, take } from "redux-saga/effects"; import history from "utils/history"; import { isNameValid } from "utils/helpers"; @@ -129,7 +129,7 @@ import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { toast } from "@appsmith/ads"; import type { MainCanvasReduxState } from "reducers/uiReducers/mainCanvasReducer"; import { UserCancelledActionExecutionError } from "sagas/ActionExecution/errorUtils"; -import { getInstanceId } from "ee/selectors/tenantSelectors"; +import { getInstanceId } from "ee/selectors/organizationSelectors"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import type { WidgetProps } from "widgets/BaseWidget"; import { nestDSL, flattenDSL, LATEST_DSL_VERSION } from "@shared/dsl"; diff --git a/app/client/src/ce/sagas/SuperUserSagas.tsx b/app/client/src/ce/sagas/SuperUserSagas.tsx index 9a9f444bd365..88131c767280 100644 --- a/app/client/src/ce/sagas/SuperUserSagas.tsx +++ b/app/client/src/ce/sagas/SuperUserSagas.tsx @@ -28,9 +28,9 @@ import { MIGRATION_STATUS, RESTART_POLL_INTERVAL, RESTART_POLL_TIMEOUT, -} from "ee/constants/tenantConstants"; -import type { FetchCurrentTenantConfigResponse } from "ee/api/TenantApi"; -import TenantApi from "ee/api/TenantApi"; +} from "ee/constants/organizationConstants"; +import type { FetchCurrentOrganizationConfigResponse } from "ee/api/OrganizationApi"; +import OrganizationApi from "ee/api/OrganizationApi"; export function* FetchAdminSettingsSaga() { const response: ApiResponse = yield call(UserApi.fetchAdminSettings); @@ -153,13 +153,13 @@ export function* RestryRestartServerPoll() { pollCount++; yield delay(RESTART_POLL_INTERVAL); try { - const response: FetchCurrentTenantConfigResponse = yield call( - TenantApi.fetchCurrentTenantConfig, + const response: FetchCurrentOrganizationConfigResponse = yield call( + OrganizationApi.fetchCurrentOrganizationConfig, ); if ( response.responseMeta.status === 200 && - response.data?.tenantConfiguration?.migrationStatus === + response.data?.organizationConfiguration?.migrationStatus === MIGRATION_STATUS.COMPLETED ) { window.location.reload(); diff --git a/app/client/src/ce/sagas/analyticsSaga.ts b/app/client/src/ce/sagas/analyticsSaga.ts index 355db4e04c0b..df5d0f4f4464 100644 --- a/app/client/src/ce/sagas/analyticsSaga.ts +++ b/app/client/src/ce/sagas/analyticsSaga.ts @@ -1,4 +1,4 @@ -import { getInstanceId } from "ee/selectors/tenantSelectors"; +import { getInstanceId } from "ee/selectors/organizationSelectors"; import { call, select } from "redux-saga/effects"; import type { APP_MODE } from "entities/App"; import { getCurrentPageId } from "selectors/editorSelectors"; diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 8dbc6ba0777a..577711a4f01c 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -1,7 +1,7 @@ import { watchActionExecutionSagas } from "ee/sagas/ActionExecution/ActionExecutionSagas"; import NavigationSagas from "ee/sagas/NavigationSagas"; import SuperUserSagas from "ee/sagas/SuperUserSagas"; -import tenantSagas from "ee/sagas/tenantSagas"; +import organizationSagas from "ee/sagas/organizationSagas"; import userSagas from "ee/sagas/userSagas"; import workspaceSagas from "ee/sagas/WorkspaceSagas"; import { watchPluginActionExecutionSagas } from "sagas/ActionExecution/PluginActionSaga"; @@ -51,10 +51,11 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; +import gitSagas from "git/sagas"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ import ternSagas from "sagas/TernSaga"; -import gitSagas from "git/sagas"; +import gitApplicationSagas from "git-artifact-helpers/application/sagas"; export const sagas = [ initSagas, @@ -96,7 +97,7 @@ export const sagas = [ NavigationSagas, editorContextSagas, AutoHeightSagas, - tenantSagas, + organizationSagas, JSLibrarySaga, LintingSaga, autoLayoutUpdateSagas, @@ -111,4 +112,5 @@ export const sagas = [ ideSagas, sendSideBySideWidgetHoverAnalyticsEventSaga, gitSagas, + gitApplicationSagas, ]; diff --git a/app/client/src/ce/sagas/tenantSagas.tsx b/app/client/src/ce/sagas/organizationSagas.tsx similarity index 69% rename from app/client/src/ce/sagas/tenantSagas.tsx rename to app/client/src/ce/sagas/organizationSagas.tsx index b9a5c247a4c7..b1d5547bd18f 100644 --- a/app/client/src/ce/sagas/tenantSagas.tsx +++ b/app/client/src/ce/sagas/organizationSagas.tsx @@ -5,27 +5,27 @@ import { } from "ee/constants/ReduxActionConstants"; import { call, put } from "redux-saga/effects"; import type { APIResponseError, ApiResponse } from "api/ApiResponses"; -import type { UpdateTenantConfigRequest } from "ee/api/TenantApi"; -import { TenantApi } from "ee/api/TenantApi"; +import type { UpdateOrganizationConfigRequest } from "ee/api/OrganizationApi"; +import { OrganizationApi } from "ee/api/OrganizationApi"; import { validateResponse } from "sagas/ErrorSagas"; import { safeCrashAppRequest } from "actions/errorActions"; import { ERROR_CODES } from "ee/constants/ApiConstants"; -import { defaultBrandingConfig as CE_defaultBrandingConfig } from "ee/reducers/tenantReducer"; +import { defaultBrandingConfig as CE_defaultBrandingConfig } from "ee/reducers/organizationReducer"; import { toast } from "@appsmith/ads"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { getFromServerWhenNoPrefetchedResult } from "sagas/helper"; -// On CE we don't expose tenant config so this shouldn't make any API calls and should just return necessary permissions for the user -export function* fetchCurrentTenantConfigSaga(action?: { - payload?: { tenantConfig?: ApiResponse }; +// On CE we don't expose organization config so this shouldn't make any API calls and should just return necessary permissions for the user +export function* fetchCurrentOrganizationConfigSaga(action?: { + payload?: { organizationConfig?: ApiResponse }; }) { - const tenantConfig = action?.payload?.tenantConfig; + const organizationConfig = action?.payload?.organizationConfig; try { const response: ApiResponse = yield call( getFromServerWhenNoPrefetchedResult, - tenantConfig, - () => call(TenantApi.fetchCurrentTenantConfig), + organizationConfig, + () => call(OrganizationApi.fetchCurrentOrganizationConfig), ); const isValidResponse: boolean = yield validateResponse(response); @@ -36,29 +36,29 @@ export function* fetchCurrentTenantConfigSaga(action?: { const data: any = response.data; yield put({ - type: ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG_SUCCESS, + type: ReduxActionTypes.FETCH_CURRENT_ORGANIZATION_CONFIG_SUCCESS, payload: data, }); AnalyticsUtil.initInstanceId(data.instanceId); } } catch (error) { yield put({ - type: ReduxActionErrorTypes.FETCH_CURRENT_TENANT_CONFIG_ERROR, + type: ReduxActionErrorTypes.FETCH_CURRENT_ORGANIZATION_CONFIG_ERROR, payload: { error, }, }); - // tenant api is UI blocking call, we have to safe crash the app if it fails + // organization api is UI blocking call, we have to safe crash the app if it fails yield put(safeCrashAppRequest()); } } -export function* updateTenantConfigSaga( - action: ReduxAction, +export function* updateOrganizationConfigSaga( + action: ReduxAction, ) { try { - const settings = action.payload.tenantConfiguration; + const settings = action.payload.organizationConfiguration; const hasSingleSessionUserSetting = settings.hasOwnProperty( "singleSessionPerUserEnabled", ); @@ -70,7 +70,7 @@ export function* updateTenantConfigSaga( ); const response: ApiResponse = yield call( - TenantApi.updateTenantConfig, + OrganizationApi.updateOrganizationConfig, action.payload, ); const isValidResponse: boolean = yield validateResponse(response); @@ -100,19 +100,19 @@ export function* updateTenantConfigSaga( }); } - // If the tenant config is not present, we need to set the default config + // If the organization config is not present, we need to set the default config yield put({ - type: ReduxActionTypes.UPDATE_TENANT_CONFIG_SUCCESS, + type: ReduxActionTypes.UPDATE_ORGANIZATION_CONFIG_SUCCESS, payload: { ...payload, - tenantConfiguration: { + organizationConfiguration: { ...CE_defaultBrandingConfig, - ...payload.tenantConfiguration, + ...payload.organizationConfiguration, }, }, }); - if (action.payload.isOnlyTenantSettings) { + if (action.payload.isOnlyOrganizationSettings) { toast.show("Successfully saved", { kind: "success", }); @@ -126,7 +126,7 @@ export function* updateTenantConfigSaga( const errorObj = error as APIResponseError; yield put({ - type: ReduxActionErrorTypes.UPDATE_TENANT_CONFIG_ERROR, + type: ReduxActionErrorTypes.UPDATE_ORGANIZATION_CONFIG_ERROR, payload: { errorObj, }, diff --git a/app/client/src/ce/sagas/userSagas.tsx b/app/client/src/ce/sagas/userSagas.tsx index da2459f5f8d6..65831655ff29 100644 --- a/app/client/src/ce/sagas/userSagas.tsx +++ b/app/client/src/ce/sagas/userSagas.tsx @@ -124,7 +124,7 @@ export function* getCurrentUserSaga(action?: { function* getSessionRecordingConfig() { const featureFlags: FeatureFlags = yield select(selectFeatureFlags); - // This is a tenant level flag to kill session recordings + // This is a organization level flag to kill session recordings // If this is true, we do not do any session recordings if (featureFlags.kill_session_recordings_enabled) { return { @@ -142,7 +142,7 @@ function* getSessionRecordingConfig() { }; } - // Now we know that both tenant and user level flags are not blocking session recordings + // Now we know that both organization and user level flags are not blocking session recordings return { enabled: true, // Check if we need to mask the session recordings from feature flags diff --git a/app/client/src/ce/selectors/appIDESelectors.ts b/app/client/src/ce/selectors/appIDESelectors.ts index 73ada5de31ae..0b67086f9831 100644 --- a/app/client/src/ce/selectors/appIDESelectors.ts +++ b/app/client/src/ce/selectors/appIDESelectors.ts @@ -9,7 +9,7 @@ import { getJSTabs, getQueryTabs } from "selectors/ideSelectors"; import type { AppState } from "ee/reducers"; import { identifyEntityFromPath } from "navigation/FocusEntity"; import { getCurrentBasePageId } from "selectors/editorSelectors"; -import { getQueryEntityItemUrl } from "ee/pages/Editor/IDE/EditorPane/Query/utils/getQueryEntityItemUrl"; +import { getQueryEntityItemUrl } from "ee/pages/AppIDE/layouts/routers/utils/getQueryEntityItemUrl"; export type EditorSegmentList = Array<{ group: string | "NA"; diff --git a/app/client/src/ce/selectors/entitiesSelector.ts b/app/client/src/ce/selectors/entitiesSelector.ts index 582e3ac5fd13..348b0c1abd87 100644 --- a/app/client/src/ce/selectors/entitiesSelector.ts +++ b/app/client/src/ce/selectors/entitiesSelector.ts @@ -18,7 +18,7 @@ import type { Action } from "entities/Action"; import { isStoredDatasource } from "entities/Action"; import { countBy, find, get, groupBy, keyBy, sortBy } from "lodash"; import ImageAlt from "assets/images/placeholder-image.svg"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import type { AppStoreState } from "reducers/entityReducers/appReducer"; import type { diff --git a/app/client/src/ce/selectors/tenantSelectors.tsx b/app/client/src/ce/selectors/organizationSelectors.tsx similarity index 52% rename from app/client/src/ce/selectors/tenantSelectors.tsx rename to app/client/src/ce/selectors/organizationSelectors.tsx index 2ab76f7e4cff..0011addfa39e 100644 --- a/app/client/src/ce/selectors/tenantSelectors.tsx +++ b/app/client/src/ce/selectors/organizationSelectors.tsx @@ -1,27 +1,27 @@ import type { AppState } from "ee/reducers"; /** - * selects the tenant permissions + * selects the organization permissions * * @param state * @returns */ -export const getTenantPermissions = (state: AppState) => { - return state.tenant?.userPermissions; +export const getOrganizationPermissions = (state: AppState) => { + return state.organization?.userPermissions; }; /** - * selects the tenant config + * selects the organization config * * @param state * @returns */ -export const getTenantConfig = (state: AppState) => { - return state.tenant?.tenantConfiguration; +export const getOrganizationConfig = (state: AppState) => { + return state.organization?.organizationConfiguration; }; /** - * selects the tenant brand colors + * selects the organization brand colors * * @returns */ @@ -33,27 +33,29 @@ export const isValidLicense = () => { return true; }; -export const isTenantLoading = (state: AppState) => { - return state.tenant?.isLoading; +export const isOrganizationLoading = (state: AppState) => { + return state.organization?.isLoading; }; export const getGoogleMapsApiKey = (state: AppState): string | undefined => - state.tenant?.tenantConfiguration?.googleMapsKey as string | undefined; + state.organization?.organizationConfiguration?.googleMapsKey as + | string + | undefined; export const getThirdPartyAuths = (state: AppState): string[] => - state.tenant?.tenantConfiguration?.thirdPartyAuths ?? []; + state.organization?.organizationConfiguration?.thirdPartyAuths ?? []; export const getIsFormLoginEnabled = (state: AppState): boolean => - state.tenant?.tenantConfiguration?.isFormLoginEnabled ?? true; + state.organization?.organizationConfiguration?.isFormLoginEnabled ?? true; export const getInstanceId = (state: AppState): string => - state.tenant?.instanceId; + state.organization?.instanceId; // eslint-disable-next-line @typescript-eslint/no-unused-vars export const shouldShowLicenseBanner = (state: AppState) => false; export const getHideWatermark = (state: AppState): boolean => - state.tenant?.tenantConfiguration?.hideWatermark; + state.organization?.organizationConfiguration?.hideWatermark; // eslint-disable-next-line @typescript-eslint/no-unused-vars export const isFreePlan = (state: AppState) => true; diff --git a/app/client/src/ce/selectors/rampSelectors.tsx b/app/client/src/ce/selectors/rampSelectors.tsx index 0d881df88581..06f755382c19 100644 --- a/app/client/src/ce/selectors/rampSelectors.tsx +++ b/app/client/src/ce/selectors/rampSelectors.tsx @@ -14,7 +14,7 @@ import { isPermitted, PERMISSION_TYPE } from "ee/utils/permissionHelpers"; const { cloudHosting, customerPortalUrl, pricingUrl } = getAppsmithConfigs(); -const tenantState = (state: AppState) => state.tenant; +const organizationState = (state: AppState) => state.organization; const uiState = (state: AppState) => state.ui; export const getRampLink = ({ @@ -26,8 +26,8 @@ export const getRampLink = ({ feature: string; isBusinessFeature?: boolean; }) => - createSelector(tenantState, (tenant) => { - const instanceId = tenant?.instanceId; + createSelector(organizationState, (organization) => { + const instanceId = organization?.instanceId; const source = cloudHosting ? "cloud" : "CE"; const RAMP_LINK_TO = isBusinessFeature ? CUSTOMER_PORTAL_URL_WITH_PARAMS( diff --git a/app/client/src/ce/utils/BusinessFeatures/adminSettingsHelpers.tsx b/app/client/src/ce/utils/BusinessFeatures/adminSettingsHelpers.tsx index f2667562545d..69df995cf5b5 100644 --- a/app/client/src/ce/utils/BusinessFeatures/adminSettingsHelpers.tsx +++ b/app/client/src/ce/utils/BusinessFeatures/adminSettingsHelpers.tsx @@ -20,11 +20,17 @@ export const getShowAdminSettings = ( export const getAdminSettingsPath = ( isEnabled: boolean, isSuperUser: boolean | undefined, - tenantPermissions: string[] = [], + organizationPermissions: string[] = [], ) => { if (isEnabled) { - return getDefaultAdminSettingsPath_EE({ isSuperUser, tenantPermissions }); + return getDefaultAdminSettingsPath_EE({ + isSuperUser, + organizationPermissions, + }); } else { - return getDefaultAdminSettingsPath_CE({ isSuperUser, tenantPermissions }); + return getDefaultAdminSettingsPath_CE({ + isSuperUser, + organizationPermissions, + }); } }; diff --git a/app/client/src/ce/utils/adminSettingsHelpers.ts b/app/client/src/ce/utils/adminSettingsHelpers.ts index 5628f50fe105..56ea44af04db 100644 --- a/app/client/src/ce/utils/adminSettingsHelpers.ts +++ b/app/client/src/ce/utils/adminSettingsHelpers.ts @@ -1,4 +1,4 @@ -import { tenantConfigConnection } from "ee/constants/tenantConstants"; +import { organizationConfigConnection } from "ee/constants/organizationConstants"; import type { AdminConfigType, Category, @@ -37,7 +37,7 @@ export const saveAllowed = ( export const getDefaultAdminSettingsPath = ( // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any - { isSuperUser, tenantPermissions: any = [] }: Record, + { isSuperUser, organizationPermissions: any = [] }: Record, ): string => { return ADMIN_SETTINGS_CATEGORY_DEFAULT_PATH; }; @@ -52,8 +52,8 @@ export const getLoginUrl = (method: string): string => { return urls[method]; }; -export const isTenantConfig = (name: string): boolean => { - const fields: string[] = tenantConfigConnection; +export const isOrganizationConfig = (name: string): boolean => { + const fields: string[] = organizationConfigConnection; return fields.includes(name); }; diff --git a/app/client/src/ce/utils/permissionHelpers.tsx b/app/client/src/ce/utils/permissionHelpers.tsx index 429422765ed0..736e06ccb9f0 100644 --- a/app/client/src/ce/utils/permissionHelpers.tsx +++ b/app/client/src/ce/utils/permissionHelpers.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ export enum PERMISSION_TYPE { /* Workspace permissions */ - CREATE_WORKSPACE = "createWorkspaces:tenant", + CREATE_WORKSPACE = "createWorkspaces:organization", MANAGE_WORKSPACE = "manage:workspaces", READ_WORKSPACE = "read:workspaces", INVITE_USER_TO_WORKSPACE = "inviteUsers:workspace", @@ -36,11 +36,11 @@ export enum PERMISSION_TYPE { MANAGE_ACTIONS = "manage:actions", DELETE_ACTIONS = "delete:actions", EXECUTE_ACTIONS = "execute:actions", - /* Git permissions */ - CONNECT_TO_GIT = "connectToGit:applications", - MANAGE_PROTECTED_BRANCHES = "manageProtectedBranches:applications", - MANAGE_DEFAULT_BRANCH = "manageDefaultBranches:applications", - MANAGE_AUTO_COMMIT = "manageAutoCommit:applications", + /* Git application permissions */ + GIT_APPLICATION_CONNECT = "connectToGit:applications", + GIT_APPLICATION_MANAGE_PROTECTED_BRANCHES = "manageProtectedBranches:applications", + GIT_APPLICATION_MANAGE_DEFAULT_BRANCH = "manageDefaultBranches:applications", + GIT_APPLICATION_MANAGE_AUTO_COMMIT = "manageAutoCommit:applications", } export enum LOGIC_FILTER { @@ -119,22 +119,33 @@ export const hasManageWorkspaceEnvironmentPermission = ( _permissions?: string[], ) => false; -export const hasConnectToGitPermission = (permissions: string[] = []) => { - return isPermitted(permissions, PERMISSION_TYPE.CONNECT_TO_GIT); +export const hasGitAppConnectPermission = (permissions: string[] = []) => { + return isPermitted(permissions, PERMISSION_TYPE.GIT_APPLICATION_CONNECT); }; -export const hasManageProtectedBranchesPermission = ( +export const hasGitAppManageProtectedBranchesPermission = ( permissions: string[] = [], ) => { - return isPermitted(permissions, PERMISSION_TYPE.MANAGE_PROTECTED_BRANCHES); + return isPermitted( + permissions, + PERMISSION_TYPE.GIT_APPLICATION_MANAGE_PROTECTED_BRANCHES, + ); }; -export const hasManageDefaultBranchPermission = ( +export const hasGitAppManageDefaultBranchPermission = ( permissions: string[] = [], ) => { - return isPermitted(permissions, PERMISSION_TYPE.MANAGE_DEFAULT_BRANCH); + return isPermitted( + permissions, + PERMISSION_TYPE.GIT_APPLICATION_MANAGE_DEFAULT_BRANCH, + ); }; -export const hasManageAutoCommitPermission = (permissions: string[] = []) => { - return isPermitted(permissions, PERMISSION_TYPE.MANAGE_AUTO_COMMIT); +export const hasGitAppManageAutoCommitPermission = ( + permissions: string[] = [], +) => { + return isPermitted( + permissions, + PERMISSION_TYPE.GIT_APPLICATION_MANAGE_AUTO_COMMIT, + ); }; diff --git a/app/client/src/components/common/Card.tsx b/app/client/src/components/common/Card.tsx index bc6e4a8d05bf..c3fa28779727 100644 --- a/app/client/src/components/common/Card.tsx +++ b/app/client/src/components/common/Card.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useMemo } from "react"; import styled from "styled-components"; import { Card as BlueprintCard, Classes } from "@blueprintjs/core"; import { omit } from "lodash"; @@ -8,6 +8,8 @@ import type { HTMLDivProps, ICardProps } from "@blueprintjs/core"; import { Button, type MenuItemProps } from "@appsmith/ads"; import GitConnectedBadge from "./GitConnectedBadge"; +import { GitCardBadge } from "git"; +import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; type CardProps = PropsWithChildren<{ backgroundColor: string; @@ -330,6 +332,16 @@ function Card({ title, titleTestId, }: CardProps) { + const isGitModEnabled = useGitModEnabled(); + + const gitBadge = useMemo(() => { + if (isGitModEnabled) { + return ; + } + + return ; + }, [isGitModEnabled]); + return ( - {showGitBadge && } + {showGitBadge ? gitBadge : null} ); } diff --git a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/unitTestUtils.ts b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/unitTestUtils.ts index 6caa81392991..8d225b555af3 100644 --- a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/unitTestUtils.ts +++ b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/unitTestUtils.ts @@ -12684,7 +12684,7 @@ export const defaultAppState = { ], slug: "jacques-s-apps", isAutoGeneratedWorkspace: true, - tenantId: "653236225e9a6424e4c04b65", + organizationId: "653236225e9a6424e4c04b65", logoUrl: "/api/v1/assets/null", new: false, }, @@ -20651,9 +20651,9 @@ export const defaultAppState = { emailVerificationEnabled: false, }, }, - tenant: { + organization: { userPermissions: [], - tenantConfiguration: { + organizationConfiguration: { brandFaviconUrl: "https://assets.appsmith.com/appsmith-favicon-orange.ico", brandColors: { diff --git a/app/client/src/components/formControls/DropDownControl.test.tsx b/app/client/src/components/formControls/DropDownControl.test.tsx index 72044cf19115..c523719ceadd 100644 --- a/app/client/src/components/formControls/DropDownControl.test.tsx +++ b/app/client/src/components/formControls/DropDownControl.test.tsx @@ -554,6 +554,7 @@ describe("DropdownControl Single select tests", () => { isLoading: false, maxTagCount: 3, isAllowClear: true, + isSearchable: true, }; beforeEach(() => { @@ -587,4 +588,34 @@ describe("DropdownControl Single select tests", () => { expect(options.length).toBe(0); }); }); + + it("should filter options when searching", async () => { + render( + + + + + , + ); + + // Find and click the dropdown to open it + const dropdownSelect = await screen.findByTestId( + "t--dropdown-actionConfiguration.testPath", + ); + + fireEvent.mouseDown(dropdownSelect.querySelector(".rc-select-selector")!); + + // Find the search input and type "Option 2" + const searchInput = screen.getByPlaceholderText("Type to search..."); + + fireEvent.change(searchInput, { target: { value: "Option 2" } }); + + // Get all visible options + const visibleOptions = screen.getAllByRole("option"); + + // // Should only show one option + expect(visibleOptions).toHaveLength(1); + // The visible option should be "Option 1" + expect(visibleOptions[0]).toHaveTextContent("Option 2"); + }); }); diff --git a/app/client/src/components/formControls/DropDownControl.tsx b/app/client/src/components/formControls/DropDownControl.tsx index 63c3708ea8c6..5aa7fa449252 100644 --- a/app/client/src/components/formControls/DropDownControl.tsx +++ b/app/client/src/components/formControls/DropDownControl.tsx @@ -466,6 +466,10 @@ function renderDropdown( onDeselect={onRemoveOptions} onPopupScroll={handlePopupScroll} onSelect={onSelectOptions} + // Default value of optionFilterProp prop is `value` which searches the dropdown based on value and not label, + // hence explicitly setting this to label to search based on label. + // For eg. If value is `Create_ticket` and label is `Create ticket`, we should be able to search using `Create ticket`. + optionFilterProp="label" placeholder={props.placeholderText} showSearch={props.isSearchable} value={isMultiSelect ? selectedOptions : selectedOptions[0]} diff --git a/app/client/src/components/formControls/FunctionCallingConfigControl/FunctionCallingConfigControl.tsx b/app/client/src/components/formControls/FunctionCallingConfigControl/FunctionCallingConfigControl.tsx new file mode 100644 index 000000000000..966ab852f221 --- /dev/null +++ b/app/client/src/components/formControls/FunctionCallingConfigControl/FunctionCallingConfigControl.tsx @@ -0,0 +1,31 @@ +import type { ControlType } from "constants/PropertyControlConstants"; +import React from "react"; +import { FieldArray } from "redux-form"; +import type { ControlProps } from "../BaseControl"; +import BaseControl from "../BaseControl"; +import { FunctionCallingConfigForm } from "./components/FunctionCallingConfigForm"; + +/** + * This component is used to configure the function calling for the AI assistant. + * It allows the user to add, edit and delete functions that can be used by the AI assistant. + */ +export default class FunctionCallingConfigControl extends BaseControl { + render() { + return ( + + ); + } + + getControlType(): ControlType { + return "FUNCTION_CALLING_CONFIG_FORM"; + } +} diff --git a/app/client/src/components/formControls/FunctionCallingConfigControl/components/FunctionCallingConfigForm.tsx b/app/client/src/components/formControls/FunctionCallingConfigControl/components/FunctionCallingConfigForm.tsx new file mode 100644 index 000000000000..caff26168912 --- /dev/null +++ b/app/client/src/components/formControls/FunctionCallingConfigControl/components/FunctionCallingConfigForm.tsx @@ -0,0 +1,89 @@ +import { Button, Text } from "@appsmith/ads"; +import { default as React, useCallback } from "react"; +import type { FieldArrayFieldsProps } from "redux-form"; +import styled from "styled-components"; +import { v4 as uuid } from "uuid"; +import type { FunctionCallingConfigFormToolField } from "../types"; +import { FunctionCallingConfigToolField } from "./FunctionCallingConfigToolField"; +import { FunctionCallingEmpty } from "./FunctionCallingEmpty"; + +export interface FunctionCallingConfigFormProps { + formName: string; + fields: FieldArrayFieldsProps; +} + +const Header = styled.div` + display: flex; + gap: var(--ads-v2-spaces-4); + justify-content: space-between; + margin-bottom: var(--ads-v2-spaces-4); +`; + +const ConfigItems = styled.div` + display: flex; + flex-direction: column; + gap: var(--ads-v2-spaces-4); +`; + +export const FunctionCallingConfigForm = ({ + fields, + formName, +}: FunctionCallingConfigFormProps) => { + const handleAddFunctionButtonClick = useCallback(() => { + fields.push({ + id: uuid(), + description: "", + entityId: "", + requiresApproval: false, + entityType: "Query", + }); + }, [fields]); + + const handleRemoveToolButtonClick = useCallback( + (index: number) => { + fields.remove(index); + }, + [fields], + ); + + return ( + <> +
+
+ + Function Calls + + + Add functions for the model to execute dynamically. + +
+ + +
+ + {fields.length === 0 ? ( + + ) : ( + + {fields.map((field, index) => { + return ( + + ); + })} + + )} + + ); +}; diff --git a/app/client/src/components/formControls/FunctionCallingConfigControl/components/FunctionCallingConfigToolField.tsx b/app/client/src/components/formControls/FunctionCallingConfigControl/components/FunctionCallingConfigToolField.tsx new file mode 100644 index 000000000000..e8cb942173d9 --- /dev/null +++ b/app/client/src/components/formControls/FunctionCallingConfigControl/components/FunctionCallingConfigToolField.tsx @@ -0,0 +1,173 @@ +import { Button, Text } from "@appsmith/ads"; +import type { AppState } from "ee/reducers"; +import FormControl from "pages/Editor/FormControl"; +import React, { useCallback, useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { change, formValueSelector } from "redux-form"; +import styled from "styled-components"; +import type { DropDownGroupedOptions } from "../../DropDownControl"; +import type { + FunctionCallingEntityTypeOption, + FunctionCallingEntityType, +} from "../types"; +import { selectEntityOptions } from "./selectors"; + +interface FunctionCallingConfigToolFieldProps { + fieldPath: string; + formName: string; + index: number; + onRemove: (index: number) => void; +} + +const ConfigItemRoot = styled.div` + display: flex; + flex-direction: column; + padding: var(--ads-v2-spaces-3); + border-radius: var(--ads-v2-border-radius); + border: 1px solid var(--ads-v2-color-border); + background: var(--colors-semantics-bg-inset, #f8fafc); +`; + +const ConfigItemRow = styled.div` + display: flex; + flex-direction: row; + align-items: center; + gap: var(--ads-v2-spaces-4); + justify-content: space-between; + margin-bottom: var(--ads-v2-spaces-4); +`; + +const ConfigItemSelectWrapper = styled.div` + width: 50%; + min-width: 160px; +`; + +export const FunctionCallingConfigToolField = ({ + index, + onRemove, + ...props +}: FunctionCallingConfigToolFieldProps) => { + const dispatch = useDispatch(); + const fieldValue = useSelector((state: AppState) => + formValueSelector(props.formName)(state, props.fieldPath), + ); + const entityOptions = useSelector(selectEntityOptions); + + const handleRemoveButtonClick = useCallback(() => { + onRemove(index); + }, [onRemove, index]); + + const findEntityOption = useCallback( + (entityId: string, items: FunctionCallingEntityTypeOption[]): boolean => { + return items.find(({ value }) => value === entityId) !== undefined; + }, + [entityOptions], + ); + + const findEntityType = useCallback( + (entityId: string): string => { + switch (true) { + case findEntityOption(entityId, entityOptions.Query): + return "Query"; + case findEntityOption(entityId, entityOptions.JSFunction): + return "JSFunction"; + case findEntityOption(entityId, entityOptions.SystemFunction): + return "SystemFunction"; + } + + return ""; + }, + [fieldValue.entityId, entityOptions], + ); + + useEffect( + // entityType is dependent on entityId + // Every time entityId changes, we need to find the new entityType + function handleEntityTypeChange() { + const entityType = findEntityType(fieldValue.entityId); + + dispatch( + change(props.formName, `${props.fieldPath}.entityType`, entityType), + ); + }, + [fieldValue.entityId], + ); + + return ( + + + + Function + + + {showProtectedBranchesInfo ? ( + + ) : null} diff --git a/app/client/src/git/components/ConnectSuccessModal/index.tsx b/app/client/src/git/components/ConnectSuccessModal/index.tsx index c492e5aa4bb3..a943f9db33fc 100644 --- a/app/client/src/git/components/ConnectSuccessModal/index.tsx +++ b/app/client/src/git/components/ConnectSuccessModal/index.tsx @@ -3,8 +3,11 @@ import ConnectSuccessModalView from "./ConnectSuccessModalView"; import useMetadata from "git/hooks/useMetadata"; import useConnect from "git/hooks/useConnect"; import useSettings from "git/hooks/useSettings"; +import { useGitContext } from "../GitContextProvider"; function ConnectSuccessModal() { + const { artifactDef, isManageProtectedBranchesPermitted } = useGitContext(); + const artifactType = artifactDef?.artifactType ?? null; const { isConnectSuccessModalOpen, toggleConnectSuccessModal } = useConnect(); const { toggleSettingsModal } = useSettings(); @@ -16,10 +19,12 @@ function ConnectSuccessModal() { return ( diff --git a/app/client/src/git/components/DangerZone/index.tsx b/app/client/src/git/components/DangerZone/index.tsx index 4d22c39076c1..9f8b41b3f594 100644 --- a/app/client/src/git/components/DangerZone/index.tsx +++ b/app/client/src/git/components/DangerZone/index.tsx @@ -1,6 +1,5 @@ import useAutocommit from "git/hooks/useAutocommit"; import useDisconnect from "git/hooks/useDisconnect"; -import useGitPermissions from "git/hooks/useGitPermissions"; import useSettings from "git/hooks/useSettings"; import React, { useCallback } from "react"; import DangerZoneView from "./DangerZoneView"; @@ -8,10 +7,13 @@ import useMetadata from "git/hooks/useMetadata"; import { useGitContext } from "../GitContextProvider"; function DangerZone() { - const { artifact, artifactDef } = useGitContext(); + const { + artifact, + artifactDef, + isConnectPermitted, + isManageAutocommitPermitted, + } = useGitContext(); const { closeDisconnectModal, openDisconnectModal } = useDisconnect(); - const { isConnectPermitted, isManageAutocommitPermitted } = - useGitPermissions(); const { isAutocommitEnabled, isToggleAutocommitLoading, diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 8154a1c67dec..88159a8d7048 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -1,21 +1,23 @@ import React, { createContext, useContext, useMemo } from "react"; import type { GitArtifactType } from "git/constants/enums"; -import type { ApplicationPayload } from "entities/Application"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; -import type { GitArtifactDef } from "git/store/types"; -import type { StatusTreeStruct } from "../StatusChanges/types"; +import type { GitArtifact, GitArtifactDef } from "git/types"; +import type { StatusTreeStruct } from "git/components/StatusChanges/types"; import type { Workspace } from "ee/constants/workspaceConstants"; import { noop } from "lodash"; export interface GitContextValue { artifactDef: GitArtifactDef | null; - artifact: ApplicationPayload | null; - artifacts: ApplicationPayload[] | null; + artifact: GitArtifact | null; + artifacts: GitArtifact[] | null; fetchArtifacts: () => void; workspace: Workspace | null; setImportWorkspaceId: () => void; importWorkspaceId: string | null; - isCreateArtifactPermitted: boolean; + isConnectPermitted: boolean; + isManageAutocommitPermitted: boolean; + isManageDefaultBranchPermitted: boolean; + isManageProtectedBranchesPermitted: boolean; statusTransformer: ( status: FetchStatusResponseData, ) => StatusTreeStruct[] | null; @@ -33,8 +35,8 @@ interface GitContextProviderProps { // artifact artifactType: GitArtifactType | null; baseArtifactId: string | null; - artifact: ApplicationPayload | null; - artifacts: ApplicationPayload[] | null; + artifact: GitArtifact | null; + artifacts: GitArtifact[] | null; fetchArtifacts: () => void; // workspace @@ -45,7 +47,10 @@ interface GitContextProviderProps { importWorkspaceId: string | null; // permissions - isCreateArtifactPermitted: boolean; + isConnectPermitted: boolean; + isManageAutocommitPermitted: boolean; + isManageDefaultBranchPermitted: boolean; + isManageProtectedBranchesPermitted: boolean; // artifactspecific functions statusTransformer: ( @@ -66,7 +71,10 @@ export default function GitContextProvider({ children, fetchArtifacts = noop, importWorkspaceId = null, - isCreateArtifactPermitted = false, + isConnectPermitted = false, + isManageAutocommitPermitted = false, + isManageDefaultBranchPermitted = false, + isManageProtectedBranchesPermitted = false, setImportWorkspaceId = noop, statusTransformer = NULL_NOOP, workspace = null, @@ -88,7 +96,10 @@ export default function GitContextProvider({ workspace, setImportWorkspaceId, importWorkspaceId, - isCreateArtifactPermitted, + isConnectPermitted, + isManageAutocommitPermitted, + isManageDefaultBranchPermitted, + isManageProtectedBranchesPermitted, statusTransformer, }), [ @@ -99,7 +110,10 @@ export default function GitContextProvider({ workspace, setImportWorkspaceId, importWorkspaceId, - isCreateArtifactPermitted, + isConnectPermitted, + isManageAutocommitPermitted, + isManageDefaultBranchPermitted, + isManageProtectedBranchesPermitted, statusTransformer, ], ); diff --git a/app/client/src/git/components/ImportModal/index.tsx b/app/client/src/git/components/ImportModal/index.tsx index 8192fa9e88a7..2dd82b71bbad 100644 --- a/app/client/src/git/components/ImportModal/index.tsx +++ b/app/client/src/git/components/ImportModal/index.tsx @@ -41,7 +41,7 @@ function ImportModal() { onGenerateSSHKey={fetchGlobalSSHKey} onOpenImport={null} onSubmit={onSubmit} - resetSSHKey={resetGlobalSSHKey} + resetConnectState={resetGlobalSSHKey} sshPublicKey={sshPublicKey} toggleModalOpen={toggleImportModal} /> diff --git a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx index 44bd8ee91cd2..aa4c47cf23eb 100644 --- a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx +++ b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx @@ -7,6 +7,7 @@ import useCommit from "git/hooks/useCommit"; import useDiscard from "git/hooks/useDiscard"; import usePull from "git/hooks/usePull"; import useStatus from "git/hooks/useStatus"; +import type { GitApplicationArtifact } from "git/types"; export default function TabDeploy() { const { artifact } = useGitContext(); @@ -21,7 +22,9 @@ export default function TabDeploy() { const { currentBranch } = useBranches(); const { metadata } = useMetadata(); - const lastDeployedAt = artifact?.lastDeployedAt ?? null; + // ! git tagging: need to handle last deplyed here when tagging is implemented + const lastDeployedAt = + (artifact as GitApplicationArtifact)?.lastDeployedAt ?? null; const isPullFailing = !!pullError; const statusIsClean = status?.isClean ?? false; const statusBehindCount = status?.behindCount ?? 0; diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx index 5ec638e8aa8d..d745ffc48996 100644 --- a/app/client/src/git/components/QuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -1,7 +1,6 @@ import React from "react"; import QuickActionsView from "./QuickActionsView"; import useStatusChangeCount from "./hooks/useStatusChangeCount"; -import useGitPermissions from "git/hooks/useGitPermissions"; import useAutocommit from "git/hooks/useAutocommit"; import useSettings from "git/hooks/useSettings"; import useConnect from "git/hooks/useConnect"; @@ -13,15 +12,16 @@ import useBranches from "git/hooks/useBranches"; import useConnected from "git/hooks/useConnected"; import useProtectedMode from "git/hooks/useProtectedMode"; import useInit from "git/hooks/useInit"; +import { useGitContext } from "../GitContextProvider"; function QuickActions() { + const { isConnectPermitted } = useGitContext(); const isConnected = useConnected(); const { toggleOpsModal } = useOps(); const { isFetchStatusLoading, status } = useStatus(); const { isPullLoading, pull, pullError } = usePull(); const { discard, isDiscardLoading } = useDiscard(); const isProtectedMode = useProtectedMode(); - const { isConnectPermitted } = useGitPermissions(); const { isAutocommitEnabled, isAutocommitPolling, diff --git a/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx b/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx index 95d18bf4b52a..d5cee2da3e10 100644 --- a/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx +++ b/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx @@ -22,11 +22,15 @@ import { REVOKE_ACCESS, REVOKE_EXISTING_REPOSITORIES, } from "ee/constants/messages"; -import type { ApplicationPayload } from "entities/Application"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import type { GitArtifact, GitArtifactDef } from "git/store/types"; import { noop } from "lodash"; -import { applicationArtifact } from "git/artifact-helpers/application"; +import type { + GitApplicationArtifact, + GitArtifact, + GitArtifactDef, + GitPackageArtifact, +} from "git/types"; +import { applicationArtifact } from "git-artifact-helpers/application"; const StyledModalContent = styled(ModalContent)` &&& { @@ -83,15 +87,17 @@ function RepoLimitErrorModalView({ }: RepoLimitErrorModalViewProps) { const gitConnectedArtifacts = useMemo(() => { return ( - artifacts?.filter((application: ApplicationPayload) => { - const data = application.gitApplicationMetadata; + artifacts?.filter((artifact: GitArtifact) => { + const gitMetadata = + (artifact as GitApplicationArtifact).gitApplicationMetadata || + (artifact as GitPackageArtifact).gitArtifactMetadata; return ( - data && - data.remoteUrl && - data.branchName && - data.repoName && - data.isRepoPrivate + gitMetadata && + gitMetadata.remoteUrl && + gitMetadata.branchName && + gitMetadata.repoName && + gitMetadata.isRepoPrivate ); }) ?? [] ); @@ -184,22 +190,22 @@ function RepoLimitErrorModalView({ - {gitConnectedArtifacts.map((application) => { - const { gitApplicationMetadata } = application; + {gitConnectedArtifacts.map((artifact) => { + const gitMetadata = + (artifact as GitApplicationArtifact).gitApplicationMetadata || + (artifact as GitPackageArtifact).gitArtifactMetadata; return (
- {application.name} + {artifact.name} - - {gitApplicationMetadata?.remoteUrl} - + {gitMetadata?.remoteUrl}
); diff --git a/app/client/src/pages/Editor/gitSync/hooks/gitPermissionHooks.ts b/app/client/src/pages/Editor/gitSync/hooks/gitPermissionHooks.ts index e788a9aaf880..d22f6e41da3b 100644 --- a/app/client/src/pages/Editor/gitSync/hooks/gitPermissionHooks.ts +++ b/app/client/src/pages/Editor/gitSync/hooks/gitPermissionHooks.ts @@ -1,22 +1,22 @@ import { useSelector } from "react-redux"; import { - hasConnectToGitPermission, - hasManageProtectedBranchesPermission, - hasManageDefaultBranchPermission, - hasManageAutoCommitPermission, + hasGitAppConnectPermission, + hasGitAppManageAutoCommitPermission, + hasGitAppManageDefaultBranchPermission, + hasGitAppManageProtectedBranchesPermission, } from "ee/utils/permissionHelpers"; import { getCurrentApplication } from "ee/selectors/applicationSelectors"; export const useHasConnectToGitPermission = () => { const currentApplication = useSelector(getCurrentApplication); - return hasConnectToGitPermission(currentApplication?.userPermissions); + return hasGitAppConnectPermission(currentApplication?.userPermissions); }; export const useHasManageProtectedBranchesPermission = () => { const currentApplication = useSelector(getCurrentApplication); - return hasManageProtectedBranchesPermission( + return hasGitAppManageProtectedBranchesPermission( currentApplication?.userPermissions, ); }; @@ -24,11 +24,15 @@ export const useHasManageProtectedBranchesPermission = () => { export const useHasManageDefaultBranchPermission = () => { const currentApplication = useSelector(getCurrentApplication); - return hasManageDefaultBranchPermission(currentApplication?.userPermissions); + return hasGitAppManageDefaultBranchPermission( + currentApplication?.userPermissions, + ); }; export const useHasManageAutoCommitPermission = () => { const currentApplication = useSelector(getCurrentApplication); - return hasManageAutoCommitPermission(currentApplication?.userPermissions); + return hasGitAppManageAutoCommitPermission( + currentApplication?.userPermissions, + ); }; diff --git a/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts b/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts index e4d4b7fb4b7a..6b6a18a03db0 100644 --- a/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts +++ b/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts @@ -10,7 +10,7 @@ import { useGitProtectedMode as useGitProtectedModeNew, useGitCurrentBranch as useGitCurrentBranchNew, useGitConnected as useGitConnectedNew, -} from "git"; +} from "git/hooks"; import { selectGitModEnabled } from "selectors/gitModSelectors"; export function useGitModEnabled() { diff --git a/app/client/src/pages/Editor/utils.tsx b/app/client/src/pages/Editor/utils.tsx index 02fcd76893ac..501c800b3be4 100644 --- a/app/client/src/pages/Editor/utils.tsx +++ b/app/client/src/pages/Editor/utils.tsx @@ -1,6 +1,5 @@ -import React from "react"; +import React, { useEffect, useMemo, useState } from "react"; import ReactDOM from "react-dom"; -import { useEffect, useMemo, useState } from "react"; import { useLocation } from "react-router"; import { debounce, random, sortBy } from "lodash"; import type { @@ -23,22 +22,15 @@ import type { ActionResponse } from "api/ActionAPI"; import type { Module } from "ee/constants/ModuleConstants"; import { MODULE_TYPE } from "ee/constants/ModuleConstants"; import { + dbQueryIcon, ENTITY_ICON_SIZE, EntityIcon, JsFileIconV2, - dbQueryIcon, } from "pages/Editor/Explorer/ExplorerIcons"; import { getAssetUrl } from "ee/utils/airgapHelpers"; import { type Plugin, PluginType } from "entities/Plugin"; import ImageAlt from "assets/images/placeholder-image.svg"; import { Icon } from "@appsmith/ads"; -import { - EditorEntityTab, - EditorEntityTabState, - EditorViewMode, -} from "IDE/Interfaces/EditorTypes"; -import { EditorState } from "IDE/enums"; -import { FocusEntity } from "navigation/FocusEntity"; import { objectKeys } from "@appsmith/utils"; export const draggableElement = ( @@ -456,83 +448,3 @@ export function getPluginImagesFromPlugins(plugins: Plugin[]) { return pluginImages; } - -/** - * Resolve segment and segmentMode based on entity type. - */ -export function getCurrentEntityInfo(entity: FocusEntity) { - switch (entity) { - case FocusEntity.QUERY: - case FocusEntity.API: - case FocusEntity.QUERY_MODULE_INSTANCE: - return { - segment: EditorEntityTab.QUERIES, - segmentMode: EditorEntityTabState.Edit, - }; - case FocusEntity.QUERY_LIST: - return { - segment: EditorEntityTab.QUERIES, - segmentMode: EditorEntityTabState.List, - }; - case FocusEntity.QUERY_ADD: - return { - segment: EditorEntityTab.QUERIES, - segmentMode: EditorEntityTabState.Add, - }; - case FocusEntity.JS_OBJECT: - case FocusEntity.JS_MODULE_INSTANCE: - return { - segment: EditorEntityTab.JS, - segmentMode: EditorEntityTabState.Edit, - }; - case FocusEntity.JS_OBJECT_ADD: - return { - segment: EditorEntityTab.JS, - segmentMode: EditorEntityTabState.Add, - }; - case FocusEntity.JS_OBJECT_LIST: - return { - segment: EditorEntityTab.JS, - segmentMode: EditorEntityTabState.List, - }; - case FocusEntity.CANVAS: - return { - segment: EditorEntityTab.UI, - segmentMode: EditorEntityTabState.Add, - }; - case FocusEntity.WIDGET: - return { - segment: EditorEntityTab.UI, - segmentMode: EditorEntityTabState.Edit, - }; - case FocusEntity.WIDGET_LIST: - return { - segment: EditorEntityTab.UI, - segmentMode: EditorEntityTabState.List, - }; - default: - return { - segment: EditorEntityTab.UI, - segmentMode: EditorEntityTabState.Add, - }; - } -} - -/** - * Check if use is currently working is side-by-side editor mode. - */ -export function isInSideBySideEditor({ - appState, - segment, - viewMode, -}: { - viewMode: EditorViewMode; - appState: EditorState; - segment: EditorEntityTab; -}) { - return ( - viewMode === EditorViewMode.SplitScreen && - appState === EditorState.EDITOR && - segment !== EditorEntityTab.UI - ); -} diff --git a/app/client/src/pages/UserAuth/Container.tsx b/app/client/src/pages/UserAuth/Container.tsx index ba731cd980e0..936e4b90ddb0 100644 --- a/app/client/src/pages/UserAuth/Container.tsx +++ b/app/client/src/pages/UserAuth/Container.tsx @@ -1,7 +1,7 @@ import React from "react"; import { useSelector } from "react-redux"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; import { getAssetUrl } from "ee/utils/airgapHelpers"; import LeftSideContent from "./LeftSideContent"; import { getAppsmithConfigs } from "ee/configs"; @@ -40,7 +40,7 @@ const BoxWrapper = styled.div<{ isMobileView: boolean }>` function Container(props: ContainerProps) { const { children, footer, subtitle, testId, title } = props; - const tenantConfig = useSelector(getTenantConfig); + const organizationConfig = useSelector(getOrganizationConfig); const { cloudHosting } = getAppsmithConfigs(); const isMobileDevice = useIsMobileDevice(); @@ -59,7 +59,7 @@ function Container(props: ContainerProps) { {!isMobileDevice && ( )}
diff --git a/app/client/src/pages/UserAuth/Login.tsx b/app/client/src/pages/UserAuth/Login.tsx index 76f59aa5a50e..fcac3e210b57 100644 --- a/app/client/src/pages/UserAuth/Login.tsx +++ b/app/client/src/pages/UserAuth/Login.tsx @@ -45,8 +45,8 @@ import Container from "pages/UserAuth/Container"; import { getThirdPartyAuths, getIsFormLoginEnabled, - getTenantConfig, -} from "ee/selectors/tenantSelectors"; + getOrganizationConfig, +} from "ee/selectors/organizationSelectors"; import Helmet from "react-helmet"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; @@ -97,8 +97,8 @@ export function Login(props: LoginFormProps) { const isBrandingEnabled = useFeatureFlag( FEATURE_FLAG.license_branding_enabled, ); - const tentantConfig = useSelector(getTenantConfig); - const { instanceName } = tentantConfig; + const organizationConfig = useSelector(getOrganizationConfig); + const { instanceName } = organizationConfig; const htmlPageTitle = getHTMLPageTitle(isBrandingEnabled, instanceName); const invalidCredsForgotPasswordLinkText = createMessage( LOGIN_PAGE_INVALID_CREDS_FORGOT_PASSWORD_LINK, diff --git a/app/client/src/pages/UserAuth/SignUp.tsx b/app/client/src/pages/UserAuth/SignUp.tsx index 0d5db6e3eec5..b0e3ebde1205 100644 --- a/app/client/src/pages/UserAuth/SignUp.tsx +++ b/app/client/src/pages/UserAuth/SignUp.tsx @@ -48,9 +48,9 @@ import { getIsSafeRedirectURL } from "utils/helpers"; import Container from "pages/UserAuth/Container"; import { getIsFormLoginEnabled, - getTenantConfig, + getOrganizationConfig, getThirdPartyAuths, -} from "ee/selectors/tenantSelectors"; +} from "ee/selectors/organizationSelectors"; import Helmet from "react-helmet"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; @@ -119,8 +119,8 @@ export function SignUp(props: SignUpFormProps) { const isBrandingEnabled = useFeatureFlag( FEATURE_FLAG.license_branding_enabled, ); - const tentantConfig = useSelector(getTenantConfig); - const { instanceName } = tentantConfig; + const organizationConfig = useSelector(getOrganizationConfig); + const { instanceName } = organizationConfig; const htmlPageTitle = getHTMLPageTitle(isBrandingEnabled, instanceName); const recaptchaStatus = useScript( diff --git a/app/client/src/pages/UserAuth/ThirdPartyAuth.tsx b/app/client/src/pages/UserAuth/ThirdPartyAuth.tsx index cb9077bcb631..496e61d413ac 100644 --- a/app/client/src/pages/UserAuth/ThirdPartyAuth.tsx +++ b/app/client/src/pages/UserAuth/ThirdPartyAuth.tsx @@ -6,9 +6,9 @@ import type { EventName } from "ee/utils/analyticsUtilTypes"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { useLocation } from "react-router-dom"; import { Button } from "@appsmith/ads"; -import { isTenantConfig } from "ee/utils/adminSettingsHelpers"; +import { isOrganizationConfig } from "ee/utils/adminSettingsHelpers"; import { useSelector } from "react-redux"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; const ThirdPartyAuthWrapper = styled.div` display: flex; @@ -36,7 +36,7 @@ function SocialLoginButton(props: { url: string; type: SignInType; }) { - const tenantConfiguration = useSelector(getTenantConfig); + const organizationConfiguration = useSelector(getOrganizationConfig); const location = useLocation(); const queryParams = new URLSearchParams(location.search); let url = props.url; @@ -48,8 +48,8 @@ function SocialLoginButton(props: { let buttonLabel = props.name; - if (props.name && isTenantConfig(props.name)) { - buttonLabel = tenantConfiguration[props.name]; + if (props.name && isOrganizationConfig(props.name)) { + buttonLabel = organizationConfiguration[props.name]; } return ( diff --git a/app/client/src/pages/UserAuth/index.tsx b/app/client/src/pages/UserAuth/index.tsx index 2ab6a60496a0..f7d948ef3a0b 100644 --- a/app/client/src/pages/UserAuth/index.tsx +++ b/app/client/src/pages/UserAuth/index.tsx @@ -17,7 +17,7 @@ import VerificationError from "./VerificationError"; import FooterLinks from "./FooterLinks"; import { useIsMobileDevice } from "utils/hooks/useDeviceDetect"; import { getAssetUrl } from "ee/utils/airgapHelpers"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; import { getAppsmithConfigs } from "ee/configs"; const SentryRoute = Sentry.withSentryRouting(Route); @@ -29,7 +29,7 @@ export function UserAuth() { getThemeDetails(state, ThemeMode.LIGHT), ); const isMobileDevice = useIsMobileDevice(); - const tenantConfig = useSelector(getTenantConfig); + const organizationConfig = useSelector(getOrganizationConfig); const { cloudHosting } = getAppsmithConfigs(); return ( @@ -43,7 +43,7 @@ export function UserAuth() { {isMobileDevice && ( )} diff --git a/app/client/src/pages/UserProfile/General.tsx b/app/client/src/pages/UserProfile/General.tsx index 5ba9786e2f2e..b85ddd54a19d 100644 --- a/app/client/src/pages/UserProfile/General.tsx +++ b/app/client/src/pages/UserProfile/General.tsx @@ -18,7 +18,7 @@ import { ANONYMOUS_USERNAME } from "constants/userConstants"; import { ALL_LANGUAGE_CHARACTERS_REGEX } from "constants/Regex"; import { createMessage } from "@appsmith/ads-old"; import { notEmptyValidator } from "@appsmith/ads-old"; -import { getIsFormLoginEnabled } from "ee/selectors/tenantSelectors"; +import { getIsFormLoginEnabled } from "ee/selectors/organizationSelectors"; const nameValidator = ( value: string, diff --git a/app/client/src/pages/UserProfile/index.test.tsx b/app/client/src/pages/UserProfile/index.test.tsx index d938ffd0bd3c..9e1ec87d30a4 100644 --- a/app/client/src/pages/UserProfile/index.test.tsx +++ b/app/client/src/pages/UserProfile/index.test.tsx @@ -17,8 +17,8 @@ import Login from "pages/UserAuth/Login"; const defaultStoreState = { ...unitTestBaseMockStore, - tenant: { - tenantConfiguration: {}, + organization: { + organizationConfiguration: {}, }, entities: { ...unitTestBaseMockStore.entities, diff --git a/app/client/src/pages/UserProfile/index.tsx b/app/client/src/pages/UserProfile/index.tsx index f77d74fedb50..d7ec1f27aad7 100644 --- a/app/client/src/pages/UserProfile/index.tsx +++ b/app/client/src/pages/UserProfile/index.tsx @@ -10,10 +10,8 @@ import { BackButton } from "components/utils/helperComponents"; import { useDispatch } from "react-redux"; import { fetchGlobalGitConfigInit } from "actions/gitSyncActions"; import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; -import { - fetchGitGlobalProfile, - GitGlobalProfile as GitGlobalProfileNew, -} from "git"; +import { GitGlobalProfile as GitGlobalProfileNew } from "git"; +import { gitFetchGlobalProfile } from "git/store"; function GitGlobalProfile() { const isGitModEnabled = useGitModEnabled(); @@ -64,7 +62,7 @@ function UserProfile() { useEffect( function fetchGlobalGitConfigOnInitEffect() { if (isGitModEnabled) { - dispatch(fetchGitGlobalProfile()); + dispatch(gitFetchGlobalProfile()); } else { dispatch(fetchGlobalGitConfigInit()); } diff --git a/app/client/src/pages/common/ErrorPageHeader.tsx b/app/client/src/pages/common/ErrorPageHeader.tsx index 01ce8637a9b6..50666b9caade 100644 --- a/app/client/src/pages/common/ErrorPageHeader.tsx +++ b/app/client/src/pages/common/ErrorPageHeader.tsx @@ -13,7 +13,7 @@ import ProfileDropdown from "./ProfileDropdown"; import { flushErrorsAndRedirect, flushErrors } from "actions/errorActions"; import { getSafeCrash } from "selectors/errorSelectors"; import { Indices } from "constants/Layers"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; import { getSelectedAppTheme } from "selectors/appThemingSelectors"; import { NAVIGATION_SETTINGS } from "constants/AppConstants"; import { get } from "lodash"; @@ -54,7 +54,7 @@ interface ErrorPageHeaderProps { export function ErrorPageHeader(props: ErrorPageHeaderProps) { const { flushErrors, flushErrorsAndRedirect, safeCrash, user } = props; const location = useLocation(); - const tenantConfig = useSelector(getTenantConfig); + const organizationConfig = useSelector(getOrganizationConfig); const queryParams = new URLSearchParams(location.search); let loginUrl = AUTH_LOGIN_URL; const redirectUrl = queryParams.get("redirectUrl"); @@ -77,7 +77,7 @@ export function ErrorPageHeader(props: ErrorPageHeaderProps) { return ( - {tenantConfig.brandLogoUrl && ( + {organizationConfig.brandLogoUrl && ( { @@ -88,7 +88,7 @@ export function ErrorPageHeader(props: ErrorPageHeaderProps) { Logo )} diff --git a/app/client/src/pages/common/ErrorPages/Page.tsx b/app/client/src/pages/common/ErrorPages/Page.tsx index 35b90d2b4339..0d4743305c0b 100644 --- a/app/client/src/pages/common/ErrorPages/Page.tsx +++ b/app/client/src/pages/common/ErrorPages/Page.tsx @@ -1,6 +1,6 @@ import React from "react"; import { useSelector } from "react-redux"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; import { getComplementaryGrayscaleColor } from "widgets/WidgetUtils"; import styled from "styled-components"; import type { PageErrorMessageProps } from "./Components/PageErrorMessage"; @@ -31,8 +31,8 @@ interface PageProps { function Page(props: PageProps) { const { cta, description, errorCode, errorIcon, title } = props; - const tenantConfig = useSelector(getTenantConfig); - const backgroundColor = tenantConfig.brandColors.background; + const organizationConfig = useSelector(getOrganizationConfig); + const backgroundColor = organizationConfig.brandColors.background; const textColor = getComplementaryGrayscaleColor(backgroundColor); return ( diff --git a/app/client/src/pages/common/ImportModal.tsx b/app/client/src/pages/common/ImportModal.tsx index 12cefc5dec8c..5eb89e3d2daf 100644 --- a/app/client/src/pages/common/ImportModal.tsx +++ b/app/client/src/pages/common/ImportModal.tsx @@ -31,7 +31,7 @@ import useMessages from "ee/hooks/importModal/useMessages"; import useMethods from "ee/hooks/importModal/useMethods"; import { getIsAnvilLayoutEnabled } from "layoutSystems/anvil/integrations/selectors"; import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; -import { toggleGitImportModal } from "git"; +import { gitToggleImportModal } from "git/store"; const TextWrapper = styled.div` padding: 0; @@ -228,7 +228,7 @@ function ImportModal(props: ImportModalProps) { if (isGitModEnabled) { dispatch( - toggleGitImportModal({ + gitToggleImportModal({ open: true, }), ); diff --git a/app/client/src/pages/common/MobileSidebar.tsx b/app/client/src/pages/common/MobileSidebar.tsx index 299d98717267..3d89938e2666 100644 --- a/app/client/src/pages/common/MobileSidebar.tsx +++ b/app/client/src/pages/common/MobileSidebar.tsx @@ -19,7 +19,7 @@ import { } from "ee/constants/messages"; import { getAppsmithConfigs } from "ee/configs"; import { howMuchTimeBeforeText } from "utils/helpers"; -import { getTenantPermissions } from "ee/selectors/tenantSelectors"; +import { getOrganizationPermissions } from "ee/selectors/organizationSelectors"; import { DISCORD_URL } from "constants/ThirdPartyConstants"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; @@ -85,7 +85,7 @@ const LeftPaneVersionData = styled.div` export default function MobileSideBar(props: MobileSideBarProps) { const user = useSelector(getCurrentUser); - const tenantPermissions = useSelector(getTenantPermissions); + const organizationPermissions = useSelector(getOrganizationPermissions); const { appVersion } = getAppsmithConfigs(); const howMuchTimeBefore = howMuchTimeBeforeText(appVersion.releaseDate); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); @@ -116,7 +116,7 @@ export default function MobileSideBar(props: MobileSideBarProps) { path: getAdminSettingsPath( isFeatureEnabled, user?.isSuperUser, - tenantPermissions, + organizationPermissions, ), }); }} diff --git a/app/client/src/pages/common/PageHeader.tsx b/app/client/src/pages/common/PageHeader.tsx index 80e2c01499d6..522eeddd4b29 100644 --- a/app/client/src/pages/common/PageHeader.tsx +++ b/app/client/src/pages/common/PageHeader.tsx @@ -8,7 +8,7 @@ import type { AppState } from "ee/reducers"; import type { User } from "constants/userConstants"; import { useIsMobileDevice } from "utils/hooks/useDeviceDetect"; import { getTemplateNotificationSeenAction } from "actions/templateActions"; -import { shouldShowLicenseBanner } from "ee/selectors/tenantSelectors"; +import { shouldShowLicenseBanner } from "ee/selectors/organizationSelectors"; import { Banner } from "ee/utils/licenseHelpers"; import bootIntercom from "utils/bootIntercom"; import EntitySearchBar from "pages/common/SearchBar/EntitySearchBar"; diff --git a/app/client/src/pages/common/PageWrapper.tsx b/app/client/src/pages/common/PageWrapper.tsx index b7a7ba755a47..4ce4f1bd4c6c 100644 --- a/app/client/src/pages/common/PageWrapper.tsx +++ b/app/client/src/pages/common/PageWrapper.tsx @@ -8,7 +8,7 @@ import { } from "ee/utils/BusinessFeatures/brandingPageHelpers"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; import { useSelector } from "react-redux"; export const Wrapper = styled.section<{ isFixed?: boolean }>` @@ -68,8 +68,8 @@ export function PageWrapper(props: PageWrapperProps) { const isBrandingEnabled = useFeatureFlag( FEATURE_FLAG?.license_branding_enabled, ); - const tentantConfig = useSelector(getTenantConfig); - const { instanceName } = tentantConfig; + const organizationConfig = useSelector(getOrganizationConfig); + const { instanceName } = organizationConfig; const titleSuffix = useMemo( () => getHTMLPageTitle(isBrandingEnabled, instanceName), diff --git a/app/client/src/pages/common/SearchBar/EntitySearchBar.tsx b/app/client/src/pages/common/SearchBar/EntitySearchBar.tsx index 71e2c00ce521..ada799f13174 100644 --- a/app/client/src/pages/common/SearchBar/EntitySearchBar.tsx +++ b/app/client/src/pages/common/SearchBar/EntitySearchBar.tsx @@ -10,7 +10,7 @@ import EditorButton from "components/editorComponents/Button"; import history from "utils/history"; import ProductUpdatesModal from "pages/Applications/ProductUpdatesModal"; import { useDispatch, useSelector } from "react-redux"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; import { getCurrentApplication, getCurrentApplicationIdForCreateNewApp, @@ -68,7 +68,7 @@ function EntitySearchBar(props: any) { useState(false); const [searchedPackages, setSearchedPackages] = useState([]); - const tenantConfig = useSelector(getTenantConfig); + const organizationConfig = useSelector(getOrganizationConfig); const isCreateNewAppFlow = useSelector( getCurrentApplicationIdForCreateNewApp, ); @@ -243,12 +243,12 @@ function EntitySearchBar(props: any) { ))} - {tenantConfig.brandLogoUrl && ( + {organizationConfig.brandLogoUrl && ( Logo )} diff --git a/app/client/src/pages/common/SearchBar/HomepageHeaderAction.tsx b/app/client/src/pages/common/SearchBar/HomepageHeaderAction.tsx index 8d259e9d7ae6..50610c34a564 100644 --- a/app/client/src/pages/common/SearchBar/HomepageHeaderAction.tsx +++ b/app/client/src/pages/common/SearchBar/HomepageHeaderAction.tsx @@ -10,7 +10,7 @@ import { } from "ee/constants/messages"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import { getCurrentApplicationIdForCreateNewApp } from "ee/selectors/applicationSelectors"; -import { getTenantPermissions } from "ee/selectors/tenantSelectors"; +import { getOrganizationPermissions } from "ee/selectors/organizationSelectors"; import { getAdminSettingsPath, getShowAdminSettings, @@ -61,7 +61,7 @@ const HomepageHeaderAction = ({ }) => { const dispatch = useDispatch(); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); - const tenantPermissions = useSelector(getTenantPermissions); + const organizationPermissions = useSelector(getOrganizationPermissions); const isCreateNewAppFlow = useSelector( getCurrentApplicationIdForCreateNewApp, ); @@ -87,7 +87,7 @@ const HomepageHeaderAction = ({ path: getAdminSettingsPath( isFeatureEnabled, user?.isSuperUser, - tenantPermissions, + organizationPermissions, ), }); }} diff --git a/app/client/src/pages/setup/SignupSuccess.tsx b/app/client/src/pages/setup/SignupSuccess.tsx index 3289f58f0667..3efe3f6ff30f 100644 --- a/app/client/src/pages/setup/SignupSuccess.tsx +++ b/app/client/src/pages/setup/SignupSuccess.tsx @@ -8,7 +8,7 @@ import { getCurrentUser } from "selectors/usersSelectors"; import UserWelcomeScreen from "pages/setup/UserWelcomeScreen"; import { Center } from "pages/setup/common"; import { Spinner } from "@appsmith/ads"; -import { isValidLicense } from "ee/selectors/tenantSelectors"; +import { isValidLicense } from "ee/selectors/organizationSelectors"; import { redirectUserAfterSignup } from "ee/utils/signupHelpers"; import { setUserSignedUpFlag } from "utils/storage"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; diff --git a/app/client/src/pages/workspace/__tests__/settings.test.tsx b/app/client/src/pages/workspace/__tests__/settings.test.tsx index 464d800eb985..cdf9124e08ae 100644 --- a/app/client/src/pages/workspace/__tests__/settings.test.tsx +++ b/app/client/src/pages/workspace/__tests__/settings.test.tsx @@ -146,7 +146,7 @@ const mockWorkspaceData = { ], slug: "sangeeth-s-apps", isAutoGeneratedWorkspace: true, - tenantId: "62a57f3c30ad39335c4dbffe", + organizationId: "62a57f3c30ad39335c4dbffe", logoUrl: "/api/v1/assets/null", new: false, }; diff --git a/app/client/src/reducers/entityReducers/metaWidgetsReducer.ts b/app/client/src/reducers/entityReducers/metaWidgetsReducer.ts index fa2624860652..eb166c267c98 100644 --- a/app/client/src/reducers/entityReducers/metaWidgetsReducer.ts +++ b/app/client/src/reducers/entityReducers/metaWidgetsReducer.ts @@ -6,7 +6,7 @@ import type { ReduxAction } from "actions/ReduxActionTypes"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import type { WidgetProps } from "widgets/BaseWidget"; import type { BatchPropertyUpdatePayload } from "actions/controlActions"; -import type { UpdateWidgetsPayload } from "./canvasWidgetsReducer"; +import type { UpdateWidgetsPayload } from "ee/reducers/entityReducers/canvasWidgetsReducer"; export interface MetaWidgetsReduxState { [widgetId: string]: FlattenedWidgetProps; diff --git a/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts b/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts index 17689a2b4cf3..c769ee9fbaa9 100644 --- a/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts +++ b/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts @@ -1,6 +1,6 @@ import type { ReduxAction } from "actions/ReduxActionTypes"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import { AppSettingsTabs } from "pages/Editor/AppSettingsPane/AppSettings"; +import { AppSettingsTabs } from "pages/AppIDE/components/AppSettings/AppSettings"; import { createReducer } from "utils/ReducerUtils"; const initialState: AppSettingsPaneReduxState = { diff --git a/app/client/src/reducers/uiReducers/errorReducer.tsx b/app/client/src/reducers/uiReducers/errorReducer.tsx index f62b5930b172..bf3e542a1ae7 100644 --- a/app/client/src/reducers/uiReducers/errorReducer.tsx +++ b/app/client/src/reducers/uiReducers/errorReducer.tsx @@ -42,11 +42,12 @@ const errorReducer = createReducer(initialState, { [ReduxActionTypes.FLUSH_ERRORS]: () => { return initialState; }, - [ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG_SUCCESS]: ( + [ReduxActionTypes.FETCH_CURRENT_ORGANIZATION_CONFIG_SUCCESS]: ( state: ErrorReduxState, ) => { if ( - state?.currentError?.sourceAction === "FETCH_CURRENT_TENANT_CONFIG_ERROR" + state?.currentError?.sourceAction === + "FETCH_CURRENT_ORGANIZATION_CONFIG_ERROR" ) { return { ...state, @@ -56,8 +57,12 @@ const errorReducer = createReducer(initialState, { return state; }, - [ReduxActionTypes.UPDATE_TENANT_CONFIG_SUCCESS]: (state: ErrorReduxState) => { - if (state?.currentError?.sourceAction === "UPDATE_TENANT_CONFIG_ERROR") { + [ReduxActionTypes.UPDATE_ORGANIZATION_CONFIG_SUCCESS]: ( + state: ErrorReduxState, + ) => { + if ( + state?.currentError?.sourceAction === "UPDATE_ORGANIZATION_CONFIG_ERROR" + ) { return { ...state, ...initialState, diff --git a/app/client/src/sagas/AnalyticsSaga.ts b/app/client/src/sagas/AnalyticsSaga.ts index 25ada435aa70..59b7b00fcdbe 100644 --- a/app/client/src/sagas/AnalyticsSaga.ts +++ b/app/client/src/sagas/AnalyticsSaga.ts @@ -31,7 +31,8 @@ import { import type { focusWidget } from "actions/widgetActions"; import { getCanvasWidgets } from "ee/selectors/entitiesSelector"; import { identifyEntityFromPath } from "navigation/FocusEntity"; -import { getCurrentEntityInfo, isInSideBySideEditor } from "pages/Editor/utils"; +import { isInSideBySideEditor } from "IDE/utils/isInSideBySideEditor"; +import { getCurrentEntityInfo } from "IDE/utils/getCurrentEntityInfo"; export function* sendAnalyticsEventSaga( type: ReduxActionType, diff --git a/app/client/src/sagas/AppThemingSaga.tsx b/app/client/src/sagas/AppThemingSaga.tsx index 283a0fcc5a3b..ac8afaea1084 100644 --- a/app/client/src/sagas/AppThemingSaga.tsx +++ b/app/client/src/sagas/AppThemingSaga.tsx @@ -38,7 +38,7 @@ import { getBetaFlag, setBetaFlag, STORAGE_KEYS } from "utils/storage"; import type { UpdateWidgetPropertyPayload } from "actions/controlActions"; import { batchUpdateMultipleWidgetProperties } from "actions/controlActions"; import { getPropertiesToUpdateForReset } from "entities/AppTheming/utils"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { getCurrentApplicationId, selectApplicationVersion, diff --git a/app/client/src/sagas/AutoLayoutUpdateSagas.tsx b/app/client/src/sagas/AutoLayoutUpdateSagas.tsx index 6a317e21f0ec..bd7ed411de86 100644 --- a/app/client/src/sagas/AutoLayoutUpdateSagas.tsx +++ b/app/client/src/sagas/AutoLayoutUpdateSagas.tsx @@ -8,7 +8,7 @@ import log from "loglevel"; import type { CanvasWidgetsReduxState, UpdateWidgetsPayload, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, diff --git a/app/client/src/sagas/BuildingBlockSagas/BuildingBlockAdditionSagas.ts b/app/client/src/sagas/BuildingBlockSagas/BuildingBlockAdditionSagas.ts index 0a27c2cc640b..4aec626779bc 100644 --- a/app/client/src/sagas/BuildingBlockSagas/BuildingBlockAdditionSagas.ts +++ b/app/client/src/sagas/BuildingBlockSagas/BuildingBlockAdditionSagas.ts @@ -11,7 +11,7 @@ import log from "loglevel"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, put, select, take } from "redux-saga/effects"; import { getCanvasWidth, diff --git a/app/client/src/sagas/BuildingBlockSagas/tests/fixtures.ts b/app/client/src/sagas/BuildingBlockSagas/tests/fixtures.ts index 7158645b4c87..e95cfcb062c6 100644 --- a/app/client/src/sagas/BuildingBlockSagas/tests/fixtures.ts +++ b/app/client/src/sagas/BuildingBlockSagas/tests/fixtures.ts @@ -1,7 +1,7 @@ import type { WidgetAddChild } from "actions/pageActions"; import type { ReduxAction } from "actions/ReduxActionTypes"; import type { WidgetDraggingUpdateParams } from "layoutSystems/common/canvasArenas/ArenaTypes"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { PaginationType, type Action } from "entities/Action"; import { PluginType } from "entities/Plugin"; diff --git a/app/client/src/sagas/CanvasSagas/AutoLayoutDraggingSagas.ts b/app/client/src/sagas/CanvasSagas/AutoLayoutDraggingSagas.ts index 7eafa1795143..a5486cb3997b 100644 --- a/app/client/src/sagas/CanvasSagas/AutoLayoutDraggingSagas.ts +++ b/app/client/src/sagas/CanvasSagas/AutoLayoutDraggingSagas.ts @@ -12,7 +12,7 @@ import { MAIN_CONTAINER_WIDGET_ID, } from "constants/WidgetConstants"; import log from "loglevel"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, put, select, takeLatest } from "redux-saga/effects"; import { getWidgets, getWidgetsMeta } from "sagas/selectors"; import { getUpdateDslAfterCreatingChild } from "sagas/WidgetAdditionSagas"; diff --git a/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts b/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts index 85dcd1e0bdb7..75b7fe3f1bd3 100644 --- a/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts +++ b/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts @@ -25,7 +25,7 @@ import log from "loglevel"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { MainCanvasReduxState } from "reducers/uiReducers/mainCanvasReducer"; import { all, call, put, select, takeLatest } from "redux-saga/effects"; import { addAndMoveBuildingBlockToCanvasSaga } from "sagas/BuildingBlockSagas/BuildingBlockAdditionSagas"; diff --git a/app/client/src/sagas/CanvasSagas/SelectionCanvasSagas.ts b/app/client/src/sagas/CanvasSagas/SelectionCanvasSagas.ts index 45cac5cae258..22a1946c0c32 100644 --- a/app/client/src/sagas/CanvasSagas/SelectionCanvasSagas.ts +++ b/app/client/src/sagas/CanvasSagas/SelectionCanvasSagas.ts @@ -12,7 +12,7 @@ import { snapToGrid } from "utils/helpers"; import { areIntersecting } from "utils/boxHelpers"; import type { WidgetProps } from "widgets/BaseWidget"; import { getWidgets } from "sagas/selectors"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import type { SelectedArenaDimensions } from "layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena"; diff --git a/app/client/src/sagas/ErrorSagas.tsx b/app/client/src/sagas/ErrorSagas.tsx index 381668da3e01..7e3a79874984 100644 --- a/app/client/src/sagas/ErrorSagas.tsx +++ b/app/client/src/sagas/ErrorSagas.tsx @@ -136,21 +136,22 @@ export function* validateResponse( if ( SERVER_ERROR_CODES.INCORRECT_BINDING_LIST_OF_WIDGET.includes( - response.responseMeta.error.code, + response.responseMeta?.error?.code, ) ) { - throw new IncorrectBindingError(response.responseMeta.error.message); + throw new IncorrectBindingError(response.responseMeta?.error?.message); } yield put({ type: ReduxActionErrorTypes.API_ERROR, payload: { - error: new Error(response.responseMeta.error.message), + error: new Error(response.responseMeta?.error?.message), logToSentry, show, }, }); - throw Error(response.responseMeta.error.message); + + throw Error(response.responseMeta?.error?.message); } export function getResponseErrorMessage(response: ApiResponse) { diff --git a/app/client/src/sagas/EvaluationsSaga.test.ts b/app/client/src/sagas/EvaluationsSaga.test.ts index 9411d9a072ba..5aa1ca60bc70 100644 --- a/app/client/src/sagas/EvaluationsSaga.test.ts +++ b/app/client/src/sagas/EvaluationsSaga.test.ts @@ -24,7 +24,7 @@ import { } from "ee/constants/ReduxActionConstants"; import { fetchPluginFormConfigsSuccess } from "actions/pluginActions"; import { createJSCollectionSuccess } from "actions/jsActionActions"; -import { getInstanceId } from "ee/selectors/tenantSelectors"; +import { getInstanceId } from "ee/selectors/organizationSelectors"; import { getApplicationLastDeployedAt, getCurrentApplicationId, diff --git a/app/client/src/sagas/EvaluationsSaga.ts b/app/client/src/sagas/EvaluationsSaga.ts index 302629efdfe0..8bbe2180b365 100644 --- a/app/client/src/sagas/EvaluationsSaga.ts +++ b/app/client/src/sagas/EvaluationsSaga.ts @@ -118,7 +118,7 @@ import { getCurrentApplicationId, getCurrentPageId, } from "selectors/editorSelectors"; -import { getInstanceId } from "ee/selectors/tenantSelectors"; +import { getInstanceId } from "ee/selectors/organizationSelectors"; import type { AffectedJSObjects, EvaluationReduxAction, diff --git a/app/client/src/sagas/IDESaga.tsx b/app/client/src/sagas/IDESaga.tsx index ced295c54dab..0f312ad3c977 100644 --- a/app/client/src/sagas/IDESaga.tsx +++ b/app/client/src/sagas/IDESaga.tsx @@ -15,8 +15,8 @@ import { queryListURL, } from "ee/RouteBuilder"; import type { EntityItem } from "ee/IDE/Interfaces/EntityItem"; -import { getQueryEntityItemUrl } from "ee/pages/Editor/IDE/EditorPane/Query/utils/getQueryEntityItemUrl"; -import { getJSEntityItemUrl } from "ee/pages/Editor/IDE/EditorPane/JS/utils/getJSEntityItemUrl"; +import { getQueryEntityItemUrl } from "ee/pages/AppIDE/layouts/routers/utils/getQueryEntityItemUrl"; +import { getJSEntityItemUrl } from "ee/pages/AppIDE/layouts/routers/utils/getJSEntityItemUrl"; import log from "loglevel"; import type { ReduxAction } from "actions/ReduxActionTypes"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; diff --git a/app/client/src/sagas/InitSagas.ts b/app/client/src/sagas/InitSagas.ts index 8ad5f7ff6cc9..3b3f635ec929 100644 --- a/app/client/src/sagas/InitSagas.ts +++ b/app/client/src/sagas/InitSagas.ts @@ -66,7 +66,7 @@ import { getDebuggerErrors } from "selectors/debuggerSelectors"; import { deleteErrorLog } from "actions/debuggerActions"; import { getCurrentUser } from "actions/authActions"; -import { getCurrentTenant } from "ee/actions/tenantActions"; +import { getCurrentOrganization } from "ee/actions/organizationActions"; import { fetchFeatureFlagsInit, fetchProductAlertInit, @@ -106,7 +106,7 @@ export interface ReduxURLChangeAction { export interface DeployConsolidatedApi { productAlert: ApiResponse; - tenantConfig: ApiResponse; + organizationConfig: ApiResponse; featureFlags: ApiResponse; userProfile: ApiResponse; pages: FetchApplicationResponse; @@ -120,7 +120,7 @@ export interface DeployConsolidatedApi { export interface EditConsolidatedApi { productAlert: ApiResponse; - tenantConfig: ApiResponse; + organizationConfig: ApiResponse; featureFlags: ApiResponse; userProfile: ApiResponse; pages: FetchApplicationResponse; @@ -285,8 +285,13 @@ export function* getInitResponses({ throw new PageNotFoundError(`Cannot find page with base id: ${basePageId}`); } - const { featureFlags, productAlert, tenantConfig, userProfile, ...rest } = - response || {}; + const { + featureFlags, + organizationConfig, + productAlert, + userProfile, + ...rest + } = response || {}; //actions originating from INITIALIZE_CURRENT_PAGE should update user details //other actions are not necessary @@ -298,7 +303,7 @@ export function* getInitResponses({ yield put(fetchFeatureFlagsInit(featureFlags)); - yield put(getCurrentTenant(false, tenantConfig)); + yield put(getCurrentOrganization(false, organizationConfig)); yield put(fetchProductAlertInit(productAlert)); yield call( diff --git a/app/client/src/sagas/ModalSagas.ts b/app/client/src/sagas/ModalSagas.ts index ebf04c2c5391..5822587e5c86 100644 --- a/app/client/src/sagas/ModalSagas.ts +++ b/app/client/src/sagas/ModalSagas.ts @@ -33,7 +33,7 @@ import { import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { updateWidgetMetaPropAndEval } from "actions/metaActions"; import { closePropertyPane, diff --git a/app/client/src/sagas/PartialImportExportSagas/PartialExportSagas.ts b/app/client/src/sagas/PartialImportExportSagas/PartialExportSagas.ts index 1822e79dfee1..84a1f87cbe64 100644 --- a/app/client/src/sagas/PartialImportExportSagas/PartialExportSagas.ts +++ b/app/client/src/sagas/PartialImportExportSagas/PartialExportSagas.ts @@ -10,7 +10,7 @@ import { import { getCurrentApplication } from "ee/selectors/applicationSelectors"; import { getFlexLayersForSelectedWidgets } from "layoutSystems/autolayout/utils/AutoLayoutUtils"; import type { FlexLayer } from "layoutSystems/autolayout/utils/types"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, put, select } from "redux-saga/effects"; import { getCurrentApplicationId, diff --git a/app/client/src/sagas/PasteWidgetUtils/index.ts b/app/client/src/sagas/PasteWidgetUtils/index.ts index d74e439161a4..d15a82d74342 100644 --- a/app/client/src/sagas/PasteWidgetUtils/index.ts +++ b/app/client/src/sagas/PasteWidgetUtils/index.ts @@ -3,7 +3,7 @@ import { GridDefaults, MAIN_CONTAINER_WIDGET_ID, } from "constants/WidgetConstants"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { call, select } from "redux-saga/effects"; import { getContainerWidgetSpacesSelector } from "selectors/editorSelectors"; import type { WidgetProps } from "widgets/BaseWidget"; diff --git a/app/client/src/sagas/PostEvaluationSagas.ts b/app/client/src/sagas/PostEvaluationSagas.ts index 86811acf8915..9d705214da76 100644 --- a/app/client/src/sagas/PostEvaluationSagas.ts +++ b/app/client/src/sagas/PostEvaluationSagas.ts @@ -36,7 +36,7 @@ import type { ActionEntityConfig } from "ee/entities/DataTree/types"; import type { SuccessfulBindings } from "utils/SuccessfulBindingsMap"; import SuccessfulBindingMap from "utils/SuccessfulBindingsMap"; import { getCurrentWorkspaceId } from "ee/selectors/selectedWorkspaceSelectors"; -import { getInstanceId } from "ee/selectors/tenantSelectors"; +import { getInstanceId } from "ee/selectors/organizationSelectors"; import type { EvalTreeResponseData } from "workers/Evaluation/types"; import { endSpan, startRootSpan } from "instrumentation/generateTraces"; import { getJSActionPathNameToDisplay } from "ee/utils/actionExecutionUtils"; diff --git a/app/client/src/sagas/SnipingModeSagas.ts b/app/client/src/sagas/SnipingModeSagas.ts index 82daf6228f19..6620a4969e14 100644 --- a/app/client/src/sagas/SnipingModeSagas.ts +++ b/app/client/src/sagas/SnipingModeSagas.ts @@ -16,7 +16,7 @@ import { } from "ee/constants/messages"; import WidgetFactory from "WidgetProvider/factory"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { setSnipingMode } from "actions/propertyPaneActions"; import { selectWidgetInitAction } from "actions/widgetSelectionActions"; import { SelectionRequestType } from "sagas/WidgetSelectUtils"; diff --git a/app/client/src/sagas/WidgetAdditionSagas.ts b/app/client/src/sagas/WidgetAdditionSagas.ts index 9f36040d190b..a64c2eea38c8 100644 --- a/app/client/src/sagas/WidgetAdditionSagas.ts +++ b/app/client/src/sagas/WidgetAdditionSagas.ts @@ -30,7 +30,7 @@ import log from "loglevel"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, put, select, takeEvery } from "redux-saga/effects"; import { getDataTree } from "selectors/dataTreeSelectors"; import { diff --git a/app/client/src/sagas/WidgetBlueprintSagas.ts b/app/client/src/sagas/WidgetBlueprintSagas.ts index 6fe85446527d..82c2146b0376 100644 --- a/app/client/src/sagas/WidgetBlueprintSagas.ts +++ b/app/client/src/sagas/WidgetBlueprintSagas.ts @@ -3,7 +3,7 @@ import { BlueprintOperationActionTypes, type WidgetBlueprint, } from "WidgetProvider/constants"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { WidgetProps } from "widgets/BaseWidget"; import { generateReactKey } from "utils/generators"; import { call, select } from "redux-saga/effects"; diff --git a/app/client/src/sagas/WidgetDeletionSagas.ts b/app/client/src/sagas/WidgetDeletionSagas.ts index f718af6802ef..e9b9f054512d 100644 --- a/app/client/src/sagas/WidgetDeletionSagas.ts +++ b/app/client/src/sagas/WidgetDeletionSagas.ts @@ -25,7 +25,7 @@ import { flattenDeep, omit, orderBy } from "lodash"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, put, select, takeEvery } from "redux-saga/effects"; import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { diff --git a/app/client/src/sagas/WidgetEnhancementHelpers.ts b/app/client/src/sagas/WidgetEnhancementHelpers.ts index bd34955ab8c6..a4c6ac2a054d 100644 --- a/app/client/src/sagas/WidgetEnhancementHelpers.ts +++ b/app/client/src/sagas/WidgetEnhancementHelpers.ts @@ -3,7 +3,7 @@ import type { WidgetType } from "constants/WidgetConstants"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import { get, set } from "lodash"; import { useSelector } from "react-redux"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { LayoutSystemTypes } from "layoutSystems/types"; import { select } from "redux-saga/effects"; import WidgetFactory from "WidgetProvider/factory"; diff --git a/app/client/src/sagas/WidgetOperationSagas.tsx b/app/client/src/sagas/WidgetOperationSagas.tsx index b2591033d4c5..7f6b1301ec14 100644 --- a/app/client/src/sagas/WidgetOperationSagas.tsx +++ b/app/client/src/sagas/WidgetOperationSagas.tsx @@ -34,7 +34,7 @@ import log from "loglevel"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { actionChannel, all, diff --git a/app/client/src/sagas/WidgetOperationUtils.test.ts b/app/client/src/sagas/WidgetOperationUtils.test.ts index 087e2f0080c5..87f966b38eda 100644 --- a/app/client/src/sagas/WidgetOperationUtils.test.ts +++ b/app/client/src/sagas/WidgetOperationUtils.test.ts @@ -1,7 +1,7 @@ import type { OccupiedSpace } from "constants/CanvasEditorConstants"; import { klona } from "klona"; import { get } from "lodash"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { WidgetProps } from "widgets/BaseWidget"; import type { FlattenedWidgetProps } from "WidgetProvider/constants"; import type { CopiedWidgetGroup } from "./WidgetOperationUtils"; diff --git a/app/client/src/sagas/WidgetOperationUtils.ts b/app/client/src/sagas/WidgetOperationUtils.ts index 16134d6046f7..1203e55ac410 100644 --- a/app/client/src/sagas/WidgetOperationUtils.ts +++ b/app/client/src/sagas/WidgetOperationUtils.ts @@ -35,7 +35,7 @@ import _, { find, isString, reduce, remove } from "lodash"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { MetaState } from "reducers/entityReducers/metaReducer"; import { all, call, select } from "redux-saga/effects"; import { reflow } from "reflow"; diff --git a/app/client/src/sagas/WidgetSelectUtils.test.ts b/app/client/src/sagas/WidgetSelectUtils.test.ts index bffe9cf9abf0..752f86d524d6 100644 --- a/app/client/src/sagas/WidgetSelectUtils.test.ts +++ b/app/client/src/sagas/WidgetSelectUtils.test.ts @@ -1,4 +1,4 @@ -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { deselectAll, pushPopWidgetSelection, diff --git a/app/client/src/sagas/WidgetSelectUtils.ts b/app/client/src/sagas/WidgetSelectUtils.ts index dde199aabee2..eab6638b5969 100644 --- a/app/client/src/sagas/WidgetSelectUtils.ts +++ b/app/client/src/sagas/WidgetSelectUtils.ts @@ -8,7 +8,7 @@ import { uniq } from "lodash"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { call, put, select } from "redux-saga/effects"; import { getWidgetImmediateChildren, diff --git a/app/client/src/sagas/WidgetSelectionSagas.ts b/app/client/src/sagas/WidgetSelectionSagas.ts index 29bb3025556e..3c893c0e84da 100644 --- a/app/client/src/sagas/WidgetSelectionSagas.ts +++ b/app/client/src/sagas/WidgetSelectionSagas.ts @@ -17,7 +17,7 @@ import { } from "actions/widgetSelectionActions"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import { APP_MODE } from "entities/App"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { all, call, put, select, take, takeLatest } from "redux-saga/effects"; import type { SetSelectionResult } from "sagas/WidgetSelectUtils"; import { diff --git a/app/client/src/sagas/autoHeightSagas/batcher.ts b/app/client/src/sagas/autoHeightSagas/batcher.ts index 9060ce248022..63de751adab8 100644 --- a/app/client/src/sagas/autoHeightSagas/batcher.ts +++ b/app/client/src/sagas/autoHeightSagas/batcher.ts @@ -3,7 +3,7 @@ import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import type { UpdateWidgetAutoHeightPayload } from "actions/autoHeightActions"; import { updateAndSaveLayout } from "actions/pageActions"; import log from "loglevel"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { put, select } from "redux-saga/effects"; import { getWidgets } from "sagas/selectors"; import { getIsDraggingOrResizing } from "selectors/widgetSelectors"; diff --git a/app/client/src/sagas/autoHeightSagas/containers.ts b/app/client/src/sagas/autoHeightSagas/containers.ts index 1bc664ba1b91..4635e72ec517 100644 --- a/app/client/src/sagas/autoHeightSagas/containers.ts +++ b/app/client/src/sagas/autoHeightSagas/containers.ts @@ -2,7 +2,7 @@ import type { ReduxAction } from "actions/ReduxActionTypes"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import { GridDefaults } from "constants/WidgetConstants"; import log from "loglevel"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { call, put, select } from "redux-saga/effects"; import { getMinHeightBasedOnChildren, shouldWidgetsCollapse } from "./helpers"; import { getCanvasHeightOffset } from "utils/WidgetSizeUtils"; diff --git a/app/client/src/sagas/autoHeightSagas/helpers.ts b/app/client/src/sagas/autoHeightSagas/helpers.ts index 3ac3086a9d53..cec3f67fffee 100644 --- a/app/client/src/sagas/autoHeightSagas/helpers.ts +++ b/app/client/src/sagas/autoHeightSagas/helpers.ts @@ -8,7 +8,7 @@ import type { AutoHeightLayoutTreeReduxState } from "reducers/entityReducers/aut import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { select } from "redux-saga/effects"; import { getWidgetMetaProps, getWidgets } from "sagas/selectors"; import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; diff --git a/app/client/src/sagas/autoHeightSagas/widgets.ts b/app/client/src/sagas/autoHeightSagas/widgets.ts index 11203cfb6ea6..5ff59fe3e201 100644 --- a/app/client/src/sagas/autoHeightSagas/widgets.ts +++ b/app/client/src/sagas/autoHeightSagas/widgets.ts @@ -8,7 +8,7 @@ import log from "loglevel"; import type { CanvasWidgetsReduxState, UpdateWidgetsPayload, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { put, select } from "redux-saga/effects"; import { getCanvasHeightOffset } from "utils/WidgetSizeUtils"; import type { FlattenedWidgetProps } from "WidgetProvider/constants"; diff --git a/app/client/src/sagas/selectors.tsx b/app/client/src/sagas/selectors.tsx index a11259025b07..110da675d4e6 100644 --- a/app/client/src/sagas/selectors.tsx +++ b/app/client/src/sagas/selectors.tsx @@ -4,7 +4,7 @@ import memoize from "proxy-memoize"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { WidgetProps } from "widgets/BaseWidget"; import _, { defaults, omit } from "lodash"; import type { WidgetType } from "constants/WidgetConstants"; diff --git a/app/client/src/selectors/appSettingsPaneSelectors.tsx b/app/client/src/selectors/appSettingsPaneSelectors.tsx index c30e4032a399..db8cb3edbc99 100644 --- a/app/client/src/selectors/appSettingsPaneSelectors.tsx +++ b/app/client/src/selectors/appSettingsPaneSelectors.tsx @@ -1,4 +1,4 @@ -import { AppSettingsTabs } from "pages/Editor/AppSettingsPane/AppSettings"; +import { AppSettingsTabs } from "pages/AppIDE/components/AppSettings/AppSettings"; import type { AppState } from "ee/reducers"; import type { AppSettingsPaneReduxState } from "reducers/uiReducers/appSettingsPaneReducer"; import { createSelector } from "reselect"; diff --git a/app/client/src/selectors/debuggerSelectors.test.ts b/app/client/src/selectors/debuggerSelectors.test.ts index 824e5e1516c4..ac87f37cee1d 100644 --- a/app/client/src/selectors/debuggerSelectors.test.ts +++ b/app/client/src/selectors/debuggerSelectors.test.ts @@ -2,7 +2,7 @@ import { Severity, LOG_CATEGORY } from "entities/AppsmithConsole"; import { ENTITY_TYPE } from "ee/entities/AppsmithConsole/utils"; import LOG_TYPE from "entities/AppsmithConsole/logtype"; import type { DataTree } from "entities/DataTree/dataTreeTypes"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { PropertyEvaluationErrorType } from "utils/DynamicBindingUtils"; import { getFilteredErrors } from "./debuggerSelectors"; diff --git a/app/client/src/selectors/debuggerSelectors.tsx b/app/client/src/selectors/debuggerSelectors.tsx index 3d208435202e..507d812c25af 100644 --- a/app/client/src/selectors/debuggerSelectors.tsx +++ b/app/client/src/selectors/debuggerSelectors.tsx @@ -3,7 +3,7 @@ import type { WidgetEntity } from "ee/entities/DataTree/types"; import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { isEmpty } from "lodash"; import type { AppState } from "ee/reducers"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { createSelector } from "reselect"; import { getWidgets } from "sagas/selectors"; import { diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index 39bd1d46c1b6..2900f7a750ff 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -4,7 +4,7 @@ import type { AppState } from "ee/reducers"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { AppLayoutConfig, PageListReduxState, @@ -897,9 +897,7 @@ export const getJSCollectionDataById = createSelector( export const getJSCollectionDataByBaseId = createSelector( [ getJSCollections, - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state: AppState, baseCollectionId: any) => baseCollectionId, + (state: AppState, baseCollectionId: string) => baseCollectionId, ], (jsActions, baseCollectionId) => { const action = jsActions.find( diff --git a/app/client/src/selectors/flattenedChildCanvasSelector.ts b/app/client/src/selectors/flattenedChildCanvasSelector.ts index 5c14f078314d..0bc0917d534e 100644 --- a/app/client/src/selectors/flattenedChildCanvasSelector.ts +++ b/app/client/src/selectors/flattenedChildCanvasSelector.ts @@ -4,7 +4,7 @@ import { getLayoutSystem } from "layoutSystems/withLayoutSystemWidgetHOC"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { createSelector } from "reselect"; import { getRenderMode } from "./editorSelectors"; import { getIsMobileBreakPoint } from "sagas/selectors"; diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts index 5576f5ffe624..84494b2b3e19 100644 --- a/app/client/src/selectors/gitModSelectors.ts +++ b/app/client/src/selectors/gitModSelectors.ts @@ -1,6 +1,3 @@ -// temp file will be removed after git mod is fully rolled out - -import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors"; import { createSelector } from "reselect"; import { getCurrentGitBranch, @@ -12,20 +9,22 @@ import { selectGitProtectedMode as selectGitProtectedModeNew, selectGitOpsModalOpen as selectGitOpsModalOpenNew, selectGitConnectModalOpen as selectGitConnectModalOpenNew, -} from "git"; -import { - getCurrentBaseApplicationId, - previewModeSelector, -} from "./editorSelectors"; -import { applicationArtifact } from "git/artifact-helpers/application"; +} from "git/store/selectors"; +import type { AppState } from "ee/reducers"; +import { applicationArtifact } from "git-artifact-helpers/application"; export const selectGitModEnabled = createSelector( - selectFeatureFlags, + (state: AppState) => { + return { + ...state.ui.users.featureFlag.data, + ...state.ui.users.featureFlag.overriddenFlags, + }; + }, (featureFlags) => featureFlags.release_git_modularisation_enabled ?? false, ); export const selectGitApplicationArtifactDef = createSelector( - getCurrentBaseApplicationId, + (state: AppState) => state.entities.pageList.baseApplicationId || "", (baseApplicationId) => applicationArtifact(baseApplicationId), ); @@ -50,7 +49,8 @@ export const selectGitApplicationProtectedMode = createSelector( ); export const selectCombinedPreviewMode = createSelector( - previewModeSelector, + // need to do this to avoid circular dependency + (state: AppState) => state.ui.editor.isPreviewMode, selectGitApplicationProtectedMode, (isPreviewMode, isProtectedMode) => isPreviewMode || isProtectedMode, ); diff --git a/app/client/src/selectors/jsPaneSelectors.ts b/app/client/src/selectors/jsPaneSelectors.ts index cc5416609bc0..a41c0d31c0d3 100644 --- a/app/client/src/selectors/jsPaneSelectors.ts +++ b/app/client/src/selectors/jsPaneSelectors.ts @@ -1,5 +1,5 @@ import type { AppState } from "ee/reducers"; -import { getJSEntityItemUrl } from "ee/pages/Editor/IDE/EditorPane/JS/utils/getJSEntityItemUrl"; +import { getJSEntityItemUrl } from "ee/pages/AppIDE/layouts/routers/utils/getJSEntityItemUrl"; import type { FocusEntityInfo } from "navigation/FocusEntity"; import { identifyEntityFromPath } from "navigation/FocusEntity"; import { selectJSSegmentEditorTabs } from "ee/selectors/appIDESelectors"; diff --git a/app/client/src/selectors/propertyPaneSelectors.tsx b/app/client/src/selectors/propertyPaneSelectors.tsx index d4688112d5e2..d0d341991092 100644 --- a/app/client/src/selectors/propertyPaneSelectors.tsx +++ b/app/client/src/selectors/propertyPaneSelectors.tsx @@ -3,7 +3,7 @@ import { find, get, set } from "lodash"; import { createSelector } from "reselect"; import type { WidgetEntity } from "ee/entities/DataTree/types"; import type { DataTree, DataTreeEntity } from "entities/DataTree/dataTreeTypes"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { PropertyPaneReduxState, SelectedPropertyPanel, @@ -16,7 +16,7 @@ import { isPathDynamicTrigger, } from "utils/DynamicBindingUtils"; import { generateClassName } from "utils/generators"; -import { getGoogleMapsApiKey } from "ee/selectors/tenantSelectors"; +import { getGoogleMapsApiKey } from "ee/selectors/organizationSelectors"; import type { WidgetProps } from "widgets/BaseWidget"; import { getCanvasWidgets } from "ee/selectors/entitiesSelector"; import { getLastSelectedWidget, getSelectedWidgets } from "./ui"; diff --git a/app/client/src/selectors/widgetEnhancementSelectors.ts b/app/client/src/selectors/widgetEnhancementSelectors.ts index 7b9470971738..dcac8ae74ca6 100644 --- a/app/client/src/selectors/widgetEnhancementSelectors.ts +++ b/app/client/src/selectors/widgetEnhancementSelectors.ts @@ -2,7 +2,7 @@ import { createSelector } from "reselect"; import { get, set } from "lodash"; import type { AppState } from "ee/reducers"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { getParentWithEnhancementFn, getWidgetEnhancementFn, diff --git a/app/client/src/selectors/widgetSelectors.ts b/app/client/src/selectors/widgetSelectors.ts index 35d648da50bf..191cc3ce5d85 100644 --- a/app/client/src/selectors/widgetSelectors.ts +++ b/app/client/src/selectors/widgetSelectors.ts @@ -3,7 +3,7 @@ import type { AppState } from "ee/reducers"; import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { getExistingWidgetNames } from "sagas/selectors"; import { getNextEntityName } from "utils/AppsmithUtils"; diff --git a/app/client/src/usagePulse/utils.ts b/app/client/src/usagePulse/utils.ts index 29ed44891a5a..c4270a80f12d 100644 --- a/app/client/src/usagePulse/utils.ts +++ b/app/client/src/usagePulse/utils.ts @@ -6,7 +6,7 @@ import { getAppMode } from "ee/selectors/entitiesSelector"; import store from "store"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { FALLBACK_KEY } from "ee/constants/UsagePulse"; -import { getInstanceId } from "ee/selectors/tenantSelectors"; +import { getInstanceId } from "ee/selectors/organizationSelectors"; //TODO (Dipyaman): We should return a promise that will get resolved only on success or rejected after the retries export const fetchWithRetry = (config: { diff --git a/app/client/src/utils/BrandingUtils.ts b/app/client/src/utils/BrandingUtils.ts index d3756991ef52..5b3d2fac00a0 100644 --- a/app/client/src/utils/BrandingUtils.ts +++ b/app/client/src/utils/BrandingUtils.ts @@ -209,13 +209,13 @@ export const faivconImageValidator = ( // NOTE: the reason why the json parsing is out of selector is we don't // want to do the parsing everytime selector is called -let cachedTenantConfigParsed = {}; -const cachedTenantConfig = localStorage.getItem("tenantConfig"); +let cachedOrganizationConfigParsed = {}; +const cachedOrganizationConfig = localStorage.getItem("organizationConfig"); try { - if (cachedTenantConfig) { - cachedTenantConfigParsed = JSON.parse(cachedTenantConfig); + if (cachedOrganizationConfig) { + cachedOrganizationConfigParsed = JSON.parse(cachedOrganizationConfig); } } catch (e) {} -export { cachedTenantConfigParsed }; +export { cachedOrganizationConfigParsed }; diff --git a/app/client/src/utils/WidgetPropsUtils.tsx b/app/client/src/utils/WidgetPropsUtils.tsx index d7caf868e385..55ba6a1aebdd 100644 --- a/app/client/src/utils/WidgetPropsUtils.tsx +++ b/app/client/src/utils/WidgetPropsUtils.tsx @@ -11,7 +11,7 @@ import { import { snapToGrid } from "./helpers"; import type { OccupiedSpace } from "constants/CanvasEditorConstants"; import defaultTemplate from "templates/default"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { WidgetType } from "../WidgetProvider/factory"; import type { DSLWidget } from "WidgetProvider/constants"; import type { BlockSpace, GridProps } from "reflow/reflowTypes"; diff --git a/app/client/src/utils/formControl/FormControlRegistry.tsx b/app/client/src/utils/formControl/FormControlRegistry.tsx index 28d9e78260e8..9ee6a471e94c 100644 --- a/app/client/src/utils/formControl/FormControlRegistry.tsx +++ b/app/client/src/utils/formControl/FormControlRegistry.tsx @@ -46,6 +46,7 @@ import { type SliderControlProps, } from "components/formControls/SliderControl"; import { HybridSearchControl } from "components/formControls/HybridSearch"; +import FunctionCallingConfigControl from "components/formControls/FunctionCallingConfigControl"; /** * NOTE: If you are adding a component that uses FormControl @@ -231,6 +232,14 @@ class FormControlRegistry { return ; }, }); + FormControlFactory.registerControlBuilder( + formControlTypes.FUNCTION_CALLING_CONFIG_FORM, + { + buildPropertyControl(controlProps): JSX.Element { + return ; + }, + }, + ); } } diff --git a/app/client/src/utils/formControl/formControlTypes.ts b/app/client/src/utils/formControl/formControlTypes.ts index 6760ce112b86..86554014d3e7 100644 --- a/app/client/src/utils/formControl/formControlTypes.ts +++ b/app/client/src/utils/formControl/formControlTypes.ts @@ -23,4 +23,5 @@ export default { SLIDER: "SLIDER", RAG_DOCUMENTS_SELECTOR: "RAG_DOCUMENTS_SELECTOR", HYBRID_SEARCH: "HYBRID_SEARCH", + FUNCTION_CALLING_CONFIG_FORM: "FUNCTION_CALLING_CONFIG_FORM", }; diff --git a/app/client/src/utils/helpers.test.ts b/app/client/src/utils/helpers.test.ts index cb615e1128eb..d8266c2eecf6 100644 --- a/app/client/src/utils/helpers.test.ts +++ b/app/client/src/utils/helpers.test.ts @@ -1,7 +1,7 @@ import { RenderModes } from "constants/WidgetConstants"; import { ValidationTypes } from "constants/WidgetValidation"; import { EvaluationSubstitutionType } from "ee/entities/DataTree/types"; -import type { CanvasWidgetsReduxState } from "../reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { AutocompleteDataType } from "./autocomplete/AutocompleteDataType"; import { flattenObject, diff --git a/app/client/src/utils/helpers.tsx b/app/client/src/utils/helpers.tsx index da98b8cd1ff3..b351bc44d9d5 100644 --- a/app/client/src/utils/helpers.tsx +++ b/app/client/src/utils/helpers.tsx @@ -32,7 +32,7 @@ import { APPSMITH_GLOBAL_FUNCTIONS } from "components/editorComponents/ActionCre import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { checkContainerScrollable } from "widgets/WidgetUtils"; import { getContainerIdForCanvas } from "sagas/WidgetOperationUtils"; import scrollIntoView from "scroll-into-view-if-needed"; diff --git a/app/client/src/utils/hooks/useBrandingTheme.ts b/app/client/src/utils/hooks/useBrandingTheme.ts index 12d6df6d84d3..df0a755cb904 100644 --- a/app/client/src/utils/hooks/useBrandingTheme.ts +++ b/app/client/src/utils/hooks/useBrandingTheme.ts @@ -1,13 +1,13 @@ import { useSelector } from "react-redux"; -import { getTenantConfig } from "ee/selectors/tenantSelectors"; +import { getOrganizationConfig } from "ee/selectors/organizationSelectors"; import { useLayoutEffect } from "react"; import { getAssetUrl } from "ee/utils/airgapHelpers"; import { APPSMITH_BRAND_PRIMARY_COLOR } from "utils/BrandingUtils"; import { LightModeTheme } from "@appsmith/wds-theming"; const useBrandingTheme = () => { - const config = useSelector(getTenantConfig); + const config = useSelector(getOrganizationConfig); let activeColor: string | undefined = undefined; if ( diff --git a/app/client/src/utils/hooks/useHoverToFocusWidget.ts b/app/client/src/utils/hooks/useHoverToFocusWidget.ts index 176192674a8c..c2e06a04b74d 100644 --- a/app/client/src/utils/hooks/useHoverToFocusWidget.ts +++ b/app/client/src/utils/hooks/useHoverToFocusWidget.ts @@ -5,7 +5,7 @@ import { getAnvilSpaceDistributionStatus } from "layoutSystems/anvil/integration import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import type { AppState } from "ee/reducers"; import type React from "react"; -import { useCurrentAppState } from "pages/Editor/IDE/hooks/useCurrentAppState"; +import { useCurrentAppState } from "IDE/hooks/useCurrentAppState"; import { EditorState } from "IDE/enums"; export const useHoverToFocusWidget = ( diff --git a/app/client/src/utils/hooks/useOnUpgrade.ts b/app/client/src/utils/hooks/useOnUpgrade.ts index 29292d2b9c62..372c93932138 100644 --- a/app/client/src/utils/hooks/useOnUpgrade.ts +++ b/app/client/src/utils/hooks/useOnUpgrade.ts @@ -1,5 +1,5 @@ import { useSelector } from "react-redux"; -import { getInstanceId } from "ee/selectors/tenantSelectors"; +import { getInstanceId } from "ee/selectors/organizationSelectors"; import { CUSTOMER_PORTAL_URL_WITH_PARAMS, PRICING_PAGE_URL, diff --git a/app/client/src/utils/reflowHookUtils.ts b/app/client/src/utils/reflowHookUtils.ts index 2c3a679d671e..b70e930da158 100644 --- a/app/client/src/utils/reflowHookUtils.ts +++ b/app/client/src/utils/reflowHookUtils.ts @@ -1,6 +1,6 @@ import type { OccupiedSpace } from "constants/CanvasEditorConstants"; import { GridDefaults } from "constants/WidgetConstants"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { GridProps, ReflowedSpace, diff --git a/app/client/src/utils/storage.ts b/app/client/src/utils/storage.ts index eefd22ee09ff..0388404d2377 100644 --- a/app/client/src/utils/storage.ts +++ b/app/client/src/utils/storage.ts @@ -1,5 +1,4 @@ import log from "loglevel"; -import moment from "moment"; import localforage from "localforage"; import { isNumber } from "lodash"; import { EditorModes } from "components/editorComponents/CodeEditor/EditorConfig"; @@ -49,27 +48,6 @@ const store = localforage.createInstance({ name: "Appsmith", }); -export const resetAuthExpiration = () => { - const expireBy = moment().add(1, "h").format(); - - store.setItem(STORAGE_KEYS.AUTH_EXPIRATION, expireBy).catch((error) => { - log.error("Unable to set expiration time"); - log.error(error); - }); -}; - -export const hasAuthExpired = async () => { - const expireBy: string | null = await store.getItem( - STORAGE_KEYS.AUTH_EXPIRATION, - ); - - if (expireBy && moment().isAfter(moment(expireBy))) { - return true; - } - - return false; -}; - export const saveCopiedWidgets = async (widgetJSON: string) => { try { await store.setItem(STORAGE_KEYS.COPIED_WIDGET, widgetJSON); @@ -82,24 +60,25 @@ export const saveCopiedWidgets = async (widgetJSON: string) => { } }; -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const getStoredUsersBetaFlags = async (email: any) => { - return store.getItem(email); +type FlagsObject = Record; + +const getStoredUsersBetaFlags = async (email: string) => { + return await store.getItem(email); }; -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const setStoredUsersBetaFlags = async (email: any, userBetaFlagsObj: any) => { +const setStoredUsersBetaFlags = async ( + email: string, + userBetaFlagsObj: FlagsObject, +) => { return store.setItem(email, userBetaFlagsObj); }; -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const setBetaFlag = async (email: any, key: string, value: any) => { - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const userBetaFlagsObj: any = await getStoredUsersBetaFlags(email); +export const setBetaFlag = async ( + email: string, + key: string, + value: boolean, +) => { + const userBetaFlagsObj = await getStoredUsersBetaFlags(email); const updatedObj = { ...userBetaFlagsObj, [key]: value, @@ -108,28 +87,12 @@ export const setBetaFlag = async (email: any, key: string, value: any) => { setStoredUsersBetaFlags(email, updatedObj); }; -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const getBetaFlag = async (email: any, key: string) => { - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const userBetaFlagsObj: any = await getStoredUsersBetaFlags(email); +export const getBetaFlag = async (email: string, key: string) => { + const userBetaFlagsObj = await getStoredUsersBetaFlags(email); return userBetaFlagsObj && userBetaFlagsObj[key]; }; -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const getReflowOnBoardingFlag = async (email: any) => { - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const userBetaFlagsObj: any = await getStoredUsersBetaFlags(email); - - return ( - userBetaFlagsObj && userBetaFlagsObj[STORAGE_KEYS.REFLOW_ONBOARDED_FLAG] - ); -}; - export const getCopiedWidgets = async () => { try { const copiedWidgetData: string | null = await store.getItem( @@ -293,32 +256,6 @@ export const deleteRecentAppEntities = async (appId: string) => { } }; -export const setOnboardingFormInProgress = async (flag?: boolean) => { - try { - await store.setItem(STORAGE_KEYS.ONBOARDING_FORM_IN_PROGRESS, flag); - - return true; - } catch (error) { - log.error("An error occurred when setting ONBOARDING_FORM_IN_PROGRESS"); - log.error(error); - - return false; - } -}; - -export const getOnboardingFormInProgress = async () => { - try { - const onboardingFormInProgress = await store.getItem( - STORAGE_KEYS.ONBOARDING_FORM_IN_PROGRESS, - ); - - return onboardingFormInProgress; - } catch (error) { - log.error("An error occurred while fetching ONBOARDING_FORM_IN_PROGRESS"); - log.error(error); - } -}; - export const setEnableStartSignposting = async (flag: boolean) => { try { await store.setItem(STORAGE_KEYS.ENABLE_START_SIGNPOSTING, flag); @@ -532,37 +469,6 @@ export const getFirstTimeUserOnboardingIntroModalVisibility = async () => { } }; -export const hideConcurrentEditorWarningToast = async () => { - try { - await store.setItem( - STORAGE_KEYS.HIDE_CONCURRENT_EDITOR_WARNING_TOAST, - true, - ); - - return true; - } catch (error) { - log.error( - "An error occurred while setting HIDE_CONCURRENT_EDITOR_WARNING_TOAST", - ); - log.error(error); - } -}; - -export const getIsConcurrentEditorWarningToastHidden = async () => { - try { - const flag = await store.getItem( - STORAGE_KEYS.HIDE_CONCURRENT_EDITOR_WARNING_TOAST, - ); - - return flag; - } catch (error) { - log.error( - "An error occurred while fetching HIDE_CONCURRENT_EDITOR_WARNING_TOAST", - ); - log.error(error); - } -}; - export const getTemplateNotificationSeen = async () => { try { const seenTemplateNotifications = await store.getItem( @@ -760,115 +666,6 @@ export const isUserSignedUpFlagSet = async (email: string) => { } }; -export const getAppKbState = async (appId: string) => { - try { - const aiKBApplicationMap: Record< - string, - { - checksum: string; - pageSlugs: { - [pageId: string]: { - hasReacted: boolean; - }; - }; - } - > | null = await store.getItem(STORAGE_KEYS.AI_KNOWLEDGE_BASE); - - if (typeof aiKBApplicationMap === "object" && aiKBApplicationMap) { - return aiKBApplicationMap[appId]; - } - - return null; - } catch (error) { - log.error("An error occurred while reading AI_KNOWLEDGE_BASE"); - log.error(error); - - return null; - } -}; - -export const initAppKbState = async ( - appId: string, - checksum: string, - pageSlugs: string[], -) => { - try { - let aiKBApplicationMap: Record< - string, - { - checksum: string; - pageSlugs: { - [pageId: string]: { - hasReacted: boolean; - }; - }; - } - > | null = await store.getItem(STORAGE_KEYS.AI_KNOWLEDGE_BASE); - - if (typeof aiKBApplicationMap !== "object" || !aiKBApplicationMap) { - aiKBApplicationMap = {}; - } - - const appKbState = { - checksum, - pageSlugs: pageSlugs.reduce( - (acc, pageSlug) => { - acc[pageSlug] = { - hasReacted: false, - }; - - return acc; - }, - {} as Record, - ) as Record, - }; - - aiKBApplicationMap[appId] = appKbState; - - await store.setItem(STORAGE_KEYS.AI_KNOWLEDGE_BASE, aiKBApplicationMap); - - return appKbState; - } catch (error) { - log.error("An error occurred while updating AI_KNOWLEDGE_BASE"); - log.error(error); - } -}; - -export const reactToPageKB = async ( - appId: string, - pageId: string, - hasReacted: boolean, -) => { - try { - let aiKBApplicationMap: Record< - string, - { - checksum: string; - pageSlugs: { - [pageId: string]: { - hasReacted: boolean; - }; - }; - } - > | null = await store.getItem(STORAGE_KEYS.AI_KNOWLEDGE_BASE); - - if (typeof aiKBApplicationMap !== "object" || !aiKBApplicationMap) { - aiKBApplicationMap = {}; - } - - if (aiKBApplicationMap?.[appId]?.pageSlugs?.[pageId]) { - aiKBApplicationMap[appId].pageSlugs[pageId].hasReacted = hasReacted; - } - - await store.setItem(STORAGE_KEYS.AI_KNOWLEDGE_BASE, aiKBApplicationMap); - - return true; - } catch (error) { - log.error("An error occurred while updating AI_KNOWLEDGE_BASE"); - log.error(error); - } -}; - export const setAISuggestedPromptShownForType = async (type: string) => { try { const suggestedPromptsShownForType: Record = @@ -914,28 +711,6 @@ export const getAISuggestedPromptShownForType = async (type: string) => { } }; -export const setPartnerProgramCalloutShown = async () => { - try { - await store.setItem(STORAGE_KEYS.PARTNER_PROGRAM_CALLOUT, true); - - return true; - } catch (error) { - log.error("An error occurred while setting PARTNER_PROGRAM_CALLOUT"); - log.error(error); - } -}; - -export const getPartnerProgramCalloutShown = async () => { - try { - const flag = await store.getItem(STORAGE_KEYS.PARTNER_PROGRAM_CALLOUT); - - return flag; - } catch (error) { - log.error("An error occurred while fetching PARTNER_PROGRAM_CALLOUT"); - log.error(error); - } -}; - export const storeIDEViewMode = async (mode: EditorViewMode) => { try { await store.setItem(STORAGE_KEYS.IDE_VIEW_MODE, mode); @@ -962,17 +737,6 @@ export const retrieveIDEViewMode = async (): Promise< } }; -export const storeCodeWidgetNavigationUsed = async (count: number) => { - try { - await store.setItem(STORAGE_KEYS.CODE_WIDGET_NAVIGATION_USED, count); - - return true; - } catch (error) { - log.error("An error occurred while setting CODE_WIDGET_NAVIGATION_USED"); - log.error(error); - } -}; - export const retrieveCodeWidgetNavigationUsed = async (): Promise => { try { const mode = (await store.getItem( @@ -1018,11 +782,11 @@ Sets the override values for feature flags. @param featureFlagValues - An object containing the feature flags and their corresponding override values. -@returns {Promise} - A promise that resolves when all the feature flags have been set. +@returns A promise that resolves when all the feature flags have been set. */ export const setFeatureFlagOverrideValues = async ( featureFlagValues: OverriddenFeatureFlags, -) => { +): Promise => { for (const [flag, value] of Object.entries(featureFlagValues)) { await store.setItem(flag, value); } diff --git a/app/client/src/utils/widgetRenderUtils.test.ts b/app/client/src/utils/widgetRenderUtils.test.ts index c24b53d38101..a85f865e2af2 100644 --- a/app/client/src/utils/widgetRenderUtils.test.ts +++ b/app/client/src/utils/widgetRenderUtils.test.ts @@ -1,6 +1,6 @@ import type { WidgetEntity } from "ee/entities/DataTree/types"; import type { DataTree } from "entities/DataTree/dataTreeTypes"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer"; import { buildChildWidgetTree, diff --git a/app/client/src/utils/widgetRenderUtils.tsx b/app/client/src/utils/widgetRenderUtils.tsx index b5a841107d4c..74fab2c16147 100644 --- a/app/client/src/utils/widgetRenderUtils.tsx +++ b/app/client/src/utils/widgetRenderUtils.tsx @@ -1,7 +1,7 @@ import type { CanvasWidgetsReduxState, FlattenedWidgetProps, -} from "reducers/entityReducers/canvasWidgetsReducer"; +} from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { WidgetEntity, WidgetEntityConfig, diff --git a/app/client/src/widgets/BaseWidget.tsx b/app/client/src/widgets/BaseWidget.tsx index 2d1f8151b251..cdd457b9f248 100644 --- a/app/client/src/widgets/BaseWidget.tsx +++ b/app/client/src/widgets/BaseWidget.tsx @@ -53,7 +53,7 @@ import store from "store"; import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors"; import type { WidgetFeatures } from "utils/WidgetFeatures"; import { LayoutSystemTypes } from "layoutSystems/types"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { CopiedWidgetData, PasteDestinationInfo, diff --git a/app/client/src/widgets/ContainerWidget/widget/index.tsx b/app/client/src/widgets/ContainerWidget/widget/index.tsx index 39652fd7d433..2d8faebd81f9 100644 --- a/app/client/src/widgets/ContainerWidget/widget/index.tsx +++ b/app/client/src/widgets/ContainerWidget/widget/index.tsx @@ -39,7 +39,7 @@ import { } from "layoutSystems/common/utils/constants"; import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory"; import { generateDefaultLayoutPreset } from "layoutSystems/anvil/layoutComponents/presets/DefaultLayoutPreset"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { LayoutSystemTypes } from "layoutSystems/types"; import type { LayoutProps } from "layoutSystems/anvil/utils/anvilTypes"; import { getWidgetBluePrintUpdates } from "utils/WidgetBlueprintUtils"; diff --git a/app/client/src/widgets/FormWidget/widget/index.tsx b/app/client/src/widgets/FormWidget/widget/index.tsx index 4b6b88ffdc9b..f501a88f2bc2 100644 --- a/app/client/src/widgets/FormWidget/widget/index.tsx +++ b/app/client/src/widgets/FormWidget/widget/index.tsx @@ -23,7 +23,7 @@ import { ButtonVariantTypes, RecaptchaTypes } from "components/constants"; import { Colors } from "constants/Colors"; import { FILL_WIDGET_MIN_WIDTH } from "constants/minWidthConstants"; import { GridDefaults, WIDGET_TAGS } from "constants/WidgetConstants"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { getWidgetBluePrintUpdates } from "utils/WidgetBlueprintUtils"; import { DynamicHeight } from "utils/WidgetFeatures"; import { BlueprintOperationTypes } from "WidgetProvider/constants"; diff --git a/app/client/src/widgets/JSONFormWidget/fields/ArrayField.tsx b/app/client/src/widgets/JSONFormWidget/fields/ArrayField.tsx index 893e21588419..85383ff1656f 100644 --- a/app/client/src/widgets/JSONFormWidget/fields/ArrayField.tsx +++ b/app/client/src/widgets/JSONFormWidget/fields/ArrayField.tsx @@ -310,7 +310,7 @@ function ArrayField({ "ArrayField.useDeepEffect.setMetaInternalFieldState", ); - const currMetaInternalFieldState: FieldState<{ isValid: true }> = get( + const currMetaInternalFieldState: FieldState<{ isValid: boolean }> = get( metaInternalFieldState, name, [], diff --git a/app/client/src/widgets/ListWidgetV2/widget/defaultProps.ts b/app/client/src/widgets/ListWidgetV2/widget/defaultProps.ts index 6276ff278291..18e8cee1c205 100644 --- a/app/client/src/widgets/ListWidgetV2/widget/defaultProps.ts +++ b/app/client/src/widgets/ListWidgetV2/widget/defaultProps.ts @@ -10,7 +10,7 @@ import { import { FILL_WIDGET_MIN_WIDTH } from "constants/minWidthConstants"; import { getWidgetBluePrintUpdates } from "utils/WidgetBlueprintUtils"; import { GridDefaults } from "constants/WidgetConstants"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { FlexLayerAlignment, FlexVerticalAlignment, diff --git a/app/client/src/widgets/ListWidgetV2/widget/index.tsx b/app/client/src/widgets/ListWidgetV2/widget/index.tsx index 6f16437d3489..6705ba29bb49 100644 --- a/app/client/src/widgets/ListWidgetV2/widget/index.tsx +++ b/app/client/src/widgets/ListWidgetV2/widget/index.tsx @@ -878,7 +878,7 @@ class ListWidget extends BaseWidget< }; calculatePageNumberFromRowIndex = (index: number) => { - return Math.ceil((index + 1) / this.pageSize); + return Math.ceil((index + 1) / this.props.pageSize); }; shouldUpdatePageSize = () => { diff --git a/app/client/src/widgets/ModalWidget/widget/index.tsx b/app/client/src/widgets/ModalWidget/widget/index.tsx index 32cdf9977466..8b3090c42e92 100644 --- a/app/client/src/widgets/ModalWidget/widget/index.tsx +++ b/app/client/src/widgets/ModalWidget/widget/index.tsx @@ -33,7 +33,7 @@ import type { import { BlueprintOperationTypes } from "WidgetProvider/constants"; import IconSVG from "../icon.svg"; import ThumbnailSVG from "../thumbnail.svg"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { getWidgetBluePrintUpdates } from "utils/WidgetBlueprintUtils"; import { DynamicHeight } from "utils/WidgetFeatures"; import type { FlexLayer } from "layoutSystems/autolayout/utils/types"; diff --git a/app/client/src/widgets/StatboxWidget/widget/index.tsx b/app/client/src/widgets/StatboxWidget/widget/index.tsx index 803f53d6e99f..e4abbede2487 100644 --- a/app/client/src/widgets/StatboxWidget/widget/index.tsx +++ b/app/client/src/widgets/StatboxWidget/widget/index.tsx @@ -25,7 +25,7 @@ import ThumbnailSVG from "../thumbnail.svg"; import type { FlattenedWidgetProps } from "WidgetProvider/constants"; import { BlueprintOperationTypes } from "WidgetProvider/constants"; import get from "lodash/get"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { DynamicHeight } from "utils/WidgetFeatures"; import { getWidgetBluePrintUpdates } from "utils/WidgetBlueprintUtils"; import type { FlexLayer } from "layoutSystems/autolayout/utils/types"; diff --git a/app/client/src/widgets/TableWidgetV2/component/StaticTable.tsx b/app/client/src/widgets/TableWidgetV2/component/StaticTable.tsx index 6af8dc468d6e..a759641e6218 100644 --- a/app/client/src/widgets/TableWidgetV2/component/StaticTable.tsx +++ b/app/client/src/widgets/TableWidgetV2/component/StaticTable.tsx @@ -42,6 +42,8 @@ type StaticTableProps = TableColumnHeaderProps & { scrollContainerStyles: any; useVirtual: boolean; tableBodyRef?: React.MutableRefObject; + isLoading: boolean; + loadMoreFromEvaluations: () => void; }; const StaticTable = (props: StaticTableProps, ref: React.Ref) => { @@ -81,6 +83,8 @@ const StaticTable = (props: StaticTableProps, ref: React.Ref) => { getTableBodyProps={props.getTableBodyProps} height={props.height} isAddRowInProgress={props.isAddRowInProgress} + isLoading={props.isLoading} + loadMoreFromEvaluations={props.loadMoreFromEvaluations} multiRowSelection={!!props.multiRowSelection} pageSize={props.pageSize} prepareRow={props.prepareRow} diff --git a/app/client/src/widgets/TableWidgetV2/component/Table.tsx b/app/client/src/widgets/TableWidgetV2/component/Table.tsx index 47354361b45b..5045d277d58f 100644 --- a/app/client/src/widgets/TableWidgetV2/component/Table.tsx +++ b/app/client/src/widgets/TableWidgetV2/component/Table.tsx @@ -473,8 +473,10 @@ export function Table(props: TableProps) { headerGroups={headerGroups} height={props.height} isAddRowInProgress={props.isAddRowInProgress} + isLoading={props.isLoading} isResizingColumn={isResizingColumn} isSortable={props.isSortable} + loadMoreFromEvaluations={props.nextPageClick} multiRowSelection={props?.multiRowSelection} pageSize={props.pageSize} prepareRow={prepareRow} @@ -512,8 +514,10 @@ export function Table(props: TableProps) { height={props.height} isAddRowInProgress={props.isAddRowInProgress} isInfiniteScrollEnabled={props.isInfiniteScrollEnabled} + isLoading={props.isLoading} isResizingColumn={isResizingColumn} isSortable={props.isSortable} + loadMoreFromEvaluations={props.nextPageClick} multiRowSelection={props?.multiRowSelection} pageSize={props.pageSize} prepareRow={prepareRow} diff --git a/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/index.tsx b/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/index.tsx new file mode 100644 index 000000000000..f2cb83e1cba0 --- /dev/null +++ b/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/index.tsx @@ -0,0 +1,59 @@ +import React, { type Ref } from "react"; +import type { Row as ReactTableRowType } from "react-table"; +import { type ReactElementType } from "react-window"; +import InfiniteLoader from "react-window-infinite-loader"; +import type SimpleBar from "simplebar-react"; +import type { TableSizes } from "../../Constants"; +import { useInfiniteVirtualization } from "./useInfiniteVirtualization"; +import { FixedInfiniteVirtualList } from "../VirtualList"; + +interface InfiniteScrollBodyProps { + rows: ReactTableRowType>[]; + height: number; + tableSizes: TableSizes; + innerElementType?: ReactElementType; + isLoading: boolean; + totalRecordsCount?: number; + itemCount: number; + loadMoreFromEvaluations: () => void; + pageSize: number; +} + +const InfiniteScrollBody = React.forwardRef( + (props: InfiniteScrollBodyProps, ref: Ref) => { + const { isLoading, loadMoreFromEvaluations, pageSize, rows } = props; + const { isItemLoaded, itemCount, loadMoreItems } = + useInfiniteVirtualization({ + rows, + totalRecordsCount: rows.length, + isLoading, + loadMore: loadMoreFromEvaluations, + pageSize, + }); + + return ( +
+ + {({ onItemsRendered, ref: infiniteLoaderRef }) => ( + + )} + +
+ ); + }, +); + +export default InfiniteScrollBody; diff --git a/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/useInfiniteVirtualization.test.tsx b/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/useInfiniteVirtualization.test.tsx new file mode 100644 index 000000000000..946a240874b1 --- /dev/null +++ b/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/useInfiniteVirtualization.test.tsx @@ -0,0 +1,152 @@ +import { renderHook } from "@testing-library/react-hooks"; +import { useInfiniteVirtualization } from "./useInfiniteVirtualization"; +import { act } from "@testing-library/react"; +import type { Row as ReactTableRowType } from "react-table"; + +describe("useInfiniteVirtualization", () => { + const mockRows: ReactTableRowType>[] = [ + { + id: "1", + original: { id: 1, name: "Test 1" }, + index: 0, + cells: [], + values: {}, + getRowProps: jest.fn(), + allCells: [], + subRows: [], + isExpanded: false, + canExpand: false, + depth: 0, + toggleRowExpanded: jest.fn(), + state: {}, + toggleRowSelected: jest.fn(), + getToggleRowExpandedProps: jest.fn(), + isSelected: false, + isSomeSelected: false, + isGrouped: false, + groupByID: "", + groupByVal: "", + leafRows: [], + getToggleRowSelectedProps: jest.fn(), + setState: jest.fn(), + }, + { + id: "2", + original: { id: 2, name: "Test 2" }, + index: 1, + cells: [], + values: {}, + getRowProps: jest.fn(), + allCells: [], + subRows: [], + isExpanded: false, + canExpand: false, + depth: 0, + toggleRowExpanded: jest.fn(), + state: {}, + toggleRowSelected: jest.fn(), + getToggleRowExpandedProps: jest.fn(), + isSelected: false, + isSomeSelected: false, + isGrouped: false, + groupByID: "", + groupByVal: "", + leafRows: [], + getToggleRowSelectedProps: jest.fn(), + setState: jest.fn(), + }, + ]; + + const defaultProps = { + rows: mockRows, + isLoading: false, + loadMore: jest.fn(), + pageSize: 10, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should return correct itemCount when totalRecordsCount is provided", () => { + const totalRecordsCount = 100; + const { result } = renderHook(() => + useInfiniteVirtualization({ + ...defaultProps, + totalRecordsCount, + }), + ); + + expect(result.current.itemCount).toBe(totalRecordsCount); + }); + + it("should return rows length as itemCount when totalRecordsCount is not provided", () => { + const { result } = renderHook(() => + useInfiniteVirtualization(defaultProps), + ); + + expect(result.current.itemCount).toBe(defaultProps.rows.length); + }); + + it("should call loadMore when loadMoreItems is called and not loading", async () => { + const { result } = renderHook(() => + useInfiniteVirtualization(defaultProps), + ); + + await act(async () => { + await result.current.loadMoreItems(0, 10); + }); + + expect(defaultProps.loadMore).toHaveBeenCalledTimes(1); + }); + + it("should not call loadMore when loadMoreItems is called and is loading", async () => { + const { result } = renderHook(() => + useInfiniteVirtualization({ + ...defaultProps, + isLoading: true, + }), + ); + + await act(async () => { + await result.current.loadMoreItems(0, 10); + }); + + expect(defaultProps.loadMore).not.toHaveBeenCalled(); + }); + + it("should return correct isItemLoaded state for different scenarios", () => { + const { result } = renderHook(() => + useInfiniteVirtualization(defaultProps), + ); + + // Index within rows length and not loading + expect(result.current.isItemLoaded(1)).toBe(true); + + // Index beyond rows length and not loading + expect(result.current.isItemLoaded(5)).toBe(false); + }); + + it("should return false for isItemLoaded when loading", () => { + const { result } = renderHook(() => + useInfiniteVirtualization({ + ...defaultProps, + isLoading: true, + }), + ); + + // Even for index within rows length, should return false when loading + expect(result.current.isItemLoaded(1)).toBe(false); + }); + + it("should return zero itemCount when there are no records", () => { + const { result } = renderHook(() => + useInfiniteVirtualization({ + ...defaultProps, + rows: [], + }), + ); + + expect(result.current.itemCount).toBe(0); + }); +}); diff --git a/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/useInfiniteVirtualization.tsx b/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/useInfiniteVirtualization.tsx new file mode 100644 index 000000000000..e43540af5fa9 --- /dev/null +++ b/app/client/src/widgets/TableWidgetV2/component/TableBody/InifiniteScrollBody/useInfiniteVirtualization.tsx @@ -0,0 +1,37 @@ +import { useCallback } from "react"; +import type { Row as ReactTableRowType } from "react-table"; + +interface InfiniteVirtualizationProps { + rows: ReactTableRowType>[]; + totalRecordsCount?: number; + isLoading: boolean; + loadMore: () => void; + pageSize: number; +} + +interface UseInfiniteVirtualizationReturn { + itemCount: number; + loadMoreItems: (startIndex: number, stopIndex: number) => void; + isItemLoaded: (index: number) => boolean; +} + +export const useInfiniteVirtualization = ({ + isLoading, + loadMore, + rows, + totalRecordsCount, +}: InfiniteVirtualizationProps): UseInfiniteVirtualizationReturn => { + const loadMoreItems = useCallback(async () => { + if (!isLoading) { + loadMore(); + } + + return Promise.resolve(); + }, [isLoading, loadMore]); + + return { + itemCount: totalRecordsCount ?? rows.length, + loadMoreItems, + isItemLoaded: (index) => !isLoading && index < rows.length, + }; +}; diff --git a/app/client/src/widgets/TableWidgetV2/component/TableBody/VirtualList.tsx b/app/client/src/widgets/TableWidgetV2/component/TableBody/VirtualList.tsx new file mode 100644 index 000000000000..c4d79bc97d5c --- /dev/null +++ b/app/client/src/widgets/TableWidgetV2/component/TableBody/VirtualList.tsx @@ -0,0 +1,91 @@ +import type { ListOnItemsRenderedProps, ReactElementType } from "react-window"; +import { FixedSizeList, areEqual } from "react-window"; +import React from "react"; +import type { ListChildComponentProps } from "react-window"; +import type { Row as ReactTableRowType } from "react-table"; +import { WIDGET_PADDING } from "constants/WidgetConstants"; +import { EmptyRow, Row } from "./Row"; +import type { TableSizes } from "../Constants"; +import type SimpleBar from "simplebar-react"; + +const rowRenderer = React.memo((rowProps: ListChildComponentProps) => { + const { data, index, style } = rowProps; + + if (index < data.length) { + const row = data[index]; + + return ( + + ); + } else { + return ; + } +}, areEqual); + +interface BaseVirtualListProps { + height: number; + tableSizes: TableSizes; + rows: ReactTableRowType>[]; + pageSize: number; + innerElementType?: ReactElementType; + outerRef?: React.Ref; + onItemsRendered?: (props: ListOnItemsRenderedProps) => void; + infiniteLoaderListRef?: React.Ref; +} + +const BaseVirtualList = React.memo(function BaseVirtualList({ + height, + infiniteLoaderListRef, + innerElementType, + onItemsRendered, + outerRef, + pageSize, + rows, + tableSizes, +}: BaseVirtualListProps) { + return ( + + {rowRenderer} + + ); +}); + +/** + * The difference between next two components is in the number of arguments they expect. + */ +export const FixedInfiniteVirtualList = React.memo( + function FixedInfiniteVirtualList(props: BaseVirtualListProps) { + return ; + }, +); + +type FixedVirtualListProps = Omit< + BaseVirtualListProps, + "onItemsRendered" | "infiniteLoaderListRef" +>; +export const FixedVirtualList = React.memo(function FixedVirtualList( + props: FixedVirtualListProps, +) { + return ; +}); diff --git a/app/client/src/widgets/TableWidgetV2/component/TableBody/index.tsx b/app/client/src/widgets/TableWidgetV2/component/TableBody/index.tsx index dd23a4155cf6..3a5f4b63a209 100644 --- a/app/client/src/widgets/TableWidgetV2/component/TableBody/index.tsx +++ b/app/client/src/widgets/TableWidgetV2/component/TableBody/index.tsx @@ -5,13 +5,13 @@ import type { TableBodyPropGetter, TableBodyProps, } from "react-table"; -import type { ListChildComponentProps, ReactElementType } from "react-window"; -import { FixedSizeList, areEqual } from "react-window"; -import { WIDGET_PADDING } from "constants/WidgetConstants"; -import { EmptyRows, EmptyRow, Row } from "./Row"; +import { type ReactElementType } from "react-window"; +import type SimpleBar from "simplebar-react"; import type { ReactTableColumnProps, TableSizes } from "../Constants"; import type { HeaderComponentProps } from "../Table"; -import type SimpleBar from "simplebar-react"; +import InfiniteScrollBody from "./InifiniteScrollBody"; +import { EmptyRows, Row } from "./Row"; +import { FixedVirtualList } from "./VirtualList"; export type BodyContextType = { accentColor: string; @@ -49,26 +49,6 @@ export const BodyContext = React.createContext({ totalColumnsWidth: 0, }); -const rowRenderer = React.memo((rowProps: ListChildComponentProps) => { - const { data, index, style } = rowProps; - - if (index < data.length) { - const row = data[index]; - - return ( - - ); - } else { - return ; - } -}, areEqual); - interface BodyPropsType { getTableBodyProps( propGetter?: TableBodyPropGetter> | undefined, @@ -80,28 +60,22 @@ interface BodyPropsType { tableSizes: TableSizes; innerElementType?: ReactElementType; isInfiniteScrollEnabled?: boolean; + isLoading: boolean; + loadMoreFromEvaluations: () => void; } const TableVirtualBodyComponent = React.forwardRef( (props: BodyPropsType, ref: Ref) => { return (
- - {rowRenderer} - + pageSize={props.pageSize} + rows={props.rows} + tableSizes={props.tableSizes} + />
); }, @@ -191,7 +165,12 @@ export const TableBody = React.forwardRef( }} > {isInfiniteScrollEnabled ? ( -
Infinite Scroll
+ ) : useVirtual ? ( void; }; const VirtualTable = (props: VirtualTableProps, ref: React.Ref) => { @@ -61,8 +63,10 @@ const VirtualTable = (props: VirtualTableProps, ref: React.Ref) => { innerElementType={VirtualTableInnerElement} isAddRowInProgress={props.isAddRowInProgress} isInfiniteScrollEnabled={props.isInfiniteScrollEnabled} + isLoading={props.isLoading} isResizingColumn={props.isResizingColumn} isSortable={props.isSortable} + loadMoreFromEvaluations={props.loadMoreFromEvaluations} multiRowSelection={!!props.multiRowSelection} pageSize={props.pageSize} prepareRow={props.prepareRow} diff --git a/app/client/src/widgets/WidgetUtils.ts b/app/client/src/widgets/WidgetUtils.ts index 286d5eeaafa1..fbbc3ddaf6a5 100644 --- a/app/client/src/widgets/WidgetUtils.ts +++ b/app/client/src/widgets/WidgetUtils.ts @@ -35,7 +35,7 @@ import { import type { SchemaItem } from "./JSONFormWidget/constants"; import { WIDGET_COMPONENT_BOUNDARY_CLASS } from "constants/componentClassNameConstants"; import punycode from "punycode"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsReducer"; interface SanitizeOptions { existingKeys?: string[]; diff --git a/app/client/src/widgets/withWidgetProps.tsx b/app/client/src/widgets/withWidgetProps.tsx index 5a0f13d6c19d..7781e3131907 100644 --- a/app/client/src/widgets/withWidgetProps.tsx +++ b/app/client/src/widgets/withWidgetProps.tsx @@ -37,7 +37,7 @@ import type { WidgetEntityConfig } from "ee/entities/DataTree/types"; import { Positioning } from "layoutSystems/common/utils/constants"; import { isAutoHeightEnabledForWidget } from "./WidgetUtils"; import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants"; -import { getGoogleMapsApiKey } from "ee/selectors/tenantSelectors"; +import { getGoogleMapsApiKey } from "ee/selectors/organizationSelectors"; import ConfigTreeActions from "utils/configTree"; import { getSelectedWidgetAncestry } from "../selectors/widgetSelectors"; import { getWidgetMinMaxDimensionsInPixel } from "layoutSystems/autolayout/utils/flexWidgetUtils"; diff --git a/app/client/src/workers/Evaluation/ReplayDSL.ts b/app/client/src/workers/Evaluation/ReplayDSL.ts index 2eee772734e5..f08dc1b47aa2 100644 --- a/app/client/src/workers/Evaluation/ReplayDSL.ts +++ b/app/client/src/workers/Evaluation/ReplayDSL.ts @@ -4,7 +4,7 @@ import { diff as deepDiff, applyChange, revertChange } from "deep-diff"; import type { DSLDiff } from "./replayUtils"; import { processDiff, getPathsFromDiff } from "./replayUtils"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; const _DIFF_ = "diff"; diff --git a/app/client/src/workers/Evaluation/fns/resetWidget.ts b/app/client/src/workers/Evaluation/fns/resetWidget.ts index cea91ca76a91..6cc90081bd2e 100644 --- a/app/client/src/workers/Evaluation/fns/resetWidget.ts +++ b/app/client/src/workers/Evaluation/fns/resetWidget.ts @@ -18,7 +18,7 @@ import { getDynamicBindings, isDynamicValue } from "utils/DynamicBindingUtils"; import { evaluateSync, setEvalContext } from "../evaluate"; import type { DescendantWidgetMap } from "sagas/WidgetOperationUtils"; import type { MetaState } from "reducers/entityReducers/metaReducer"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { EvalMetaUpdates } from "ee/workers/common/DataTreeEvaluator/types"; import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { validateAndParseWidgetProperty } from "workers/common/DataTreeEvaluator/validationUtils"; diff --git a/app/client/src/workers/Evaluation/handlers/evalTree.ts b/app/client/src/workers/Evaluation/handlers/evalTree.ts index 52b6ccacd908..cc16a6e0bc25 100644 --- a/app/client/src/workers/Evaluation/handlers/evalTree.ts +++ b/app/client/src/workers/Evaluation/handlers/evalTree.ts @@ -31,7 +31,7 @@ import { newWebWorkerSpanData, profileAsyncFn, } from "instrumentation/generateWebWorkerTraces"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer"; import type { Attributes } from "instrumentation/types"; import { updateActionsToEvalTree } from "./updateActionData"; diff --git a/app/client/src/workers/Evaluation/replayUtils.ts b/app/client/src/workers/Evaluation/replayUtils.ts index 2f9477c4f218..fc1caa5cdd14 100644 --- a/app/client/src/workers/Evaluation/replayUtils.ts +++ b/app/client/src/workers/Evaluation/replayUtils.ts @@ -1,7 +1,7 @@ import { get, set } from "lodash"; import type { Diff } from "deep-diff"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; export type DSLDiff = Diff; diff --git a/app/client/src/workers/Evaluation/types.ts b/app/client/src/workers/Evaluation/types.ts index a6e450e9d1cd..4a67a47ed98c 100644 --- a/app/client/src/workers/Evaluation/types.ts +++ b/app/client/src/workers/Evaluation/types.ts @@ -2,7 +2,7 @@ import type { unEvalAndConfigTree } from "entities/DataTree/dataTreeTypes"; import type { ActionValidationConfigMap } from "constants/PropertyControlConstants"; import type { AppTheme } from "entities/AppTheming"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer"; import type { DependencyMap, EvalError } from "utils/DynamicBindingUtils"; import type { diff --git a/app/client/test/testCommon.ts b/app/client/test/testCommon.ts index ab3fcb9d1282..02d0eda2d720 100644 --- a/app/client/test/testCommon.ts +++ b/app/client/test/testCommon.ts @@ -3,14 +3,14 @@ import { initEditorAction } from "actions/initActions"; import { setAppMode, updateCurrentPage } from "actions/pageActions"; import { APP_MODE } from "entities/App"; import { useDispatch } from "react-redux"; -import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; +import type { CanvasWidgetsReduxState } from "ee/reducers/entityReducers/canvasWidgetsReducer"; import { getCanvasWidgetsPayload } from "ee/sagas/PageSagas"; import { editorInitializer } from "utils/editor/EditorUtils"; import { extractCurrentDSL } from "utils/WidgetPropsUtils"; import type { AppState } from "ee/reducers"; import type { WidgetEntity } from "ee/entities/DataTree/types"; import urlBuilder from "ee/entities/URLRedirect/URLAssembly"; -import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsStructureReducer"; +import type { FlattenedWidgetProps } from "ee/reducers/entityReducers/canvasWidgetsStructureReducer"; import type { Page } from "entities/Page"; import { useEffect, useState } from "react"; import type { FetchPageResponse } from "api/PageApi"; diff --git a/app/client/test/testMockedWidgets.tsx b/app/client/test/testMockedWidgets.tsx index 70795c0a7295..1314cb303169 100644 --- a/app/client/test/testMockedWidgets.tsx +++ b/app/client/test/testMockedWidgets.tsx @@ -1,7 +1,7 @@ import { APP_MODE } from "entities/App"; import AppViewerPageContainer from "pages/AppViewer/AppViewerPageContainer"; import Canvas from "pages/Editor/Canvas"; -import IDE from "pages/Editor/IDE"; +import IDE from "pages/AppIDE/layouts"; import React from "react"; import { useSelector } from "react-redux"; import { getCanvasWidgetsStructure } from "ee/selectors/entitiesSelector"; @@ -18,6 +18,7 @@ export function UpdateAppViewer({ dsl }: { dsl: unknown }) { return hasLoaded ? : null; } + export function UpdatedEditor({ dsl }: { dsl: unknown }) { const hasLoaded = useMockDsl(dsl, APP_MODE.EDIT); diff --git a/app/client/yarn.lock b/app/client/yarn.lock index fb2dcfec865f..0971bdce9521 100644 --- a/app/client/yarn.lock +++ b/app/client/yarn.lock @@ -155,7 +155,7 @@ __metadata: clsx: ^2.0.0 eslint-plugin-storybook: ^0.6.10 lodash: "*" - react-aria-components: ^1.2.1 + react-aria-components: ^1.6.0 react-markdown: ^9.0.1 react-syntax-highlighter: ^15.5.0 react-transition-group: ^4.4.5 @@ -872,6 +872,88 @@ __metadata: languageName: node linkType: hard +"@azure/abort-controller@npm:^2.0.0": + version: 2.1.2 + resolution: "@azure/abort-controller@npm:2.1.2" + dependencies: + tslib: ^2.6.2 + checksum: 22176c04ea01498311c6bbd336669f6e3faffad1cbb0c9ebc6ee9c1ff2cf958fd17ce73c7354b99d8bda9fcd311325ece7bee248875279174e3fc460e8b1a63d + languageName: node + linkType: hard + +"@azure/core-auth@npm:^1.7.1, @azure/core-auth@npm:^1.8.0": + version: 1.9.0 + resolution: "@azure/core-auth@npm:1.9.0" + dependencies: + "@azure/abort-controller": ^2.0.0 + "@azure/core-util": ^1.11.0 + tslib: ^2.6.2 + checksum: 4050112188db093c5e01caca0175708c767054c0cea4202430ff43ee42a16430235752ccc0002caea1796c8f01b4f6369c878762bf4c1b2f61af1b7ac13182fc + languageName: node + linkType: hard + +"@azure/core-rest-pipeline@npm:^1.15.1": + version: 1.19.0 + resolution: "@azure/core-rest-pipeline@npm:1.19.0" + dependencies: + "@azure/abort-controller": ^2.0.0 + "@azure/core-auth": ^1.8.0 + "@azure/core-tracing": ^1.0.1 + "@azure/core-util": ^1.11.0 + "@azure/logger": ^1.0.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.0 + tslib: ^2.6.2 + checksum: e8d7631152d7af27b949f3da792a22a92a633b5744604f90e02e56e0b888e031f15f5d3384d7ca65ae851492ad0e33972f000b99600b081ceb0eb66e294454c1 + languageName: node + linkType: hard + +"@azure/core-tracing@npm:^1.0.1, @azure/core-tracing@npm:^1.1.1": + version: 1.2.0 + resolution: "@azure/core-tracing@npm:1.2.0" + dependencies: + tslib: ^2.6.2 + checksum: 202ebf411a3076bd2c48b7a4c1b63335f53be6dd97f7d53500e3191b7ed0fdad25de219f422e777fde824031fd5c67087654de0304a5c0cd67c38cdcab96117c + languageName: node + linkType: hard + +"@azure/core-util@npm:^1.11.0, @azure/core-util@npm:^1.8.1": + version: 1.11.0 + resolution: "@azure/core-util@npm:1.11.0" + dependencies: + "@azure/abort-controller": ^2.0.0 + tslib: ^2.6.2 + checksum: 91e3ec329d9eddaa66be5efb1785dad68dcb48dd779fca36e39db041673230510158ff5ca9ccef9f19c3e4d8e9af29f66a367cfc31a7b94d2541f80ef94ec797 + languageName: node + linkType: hard + +"@azure/cosmos@npm:^4.1.1": + version: 4.2.0 + resolution: "@azure/cosmos@npm:4.2.0" + dependencies: + "@azure/abort-controller": ^2.0.0 + "@azure/core-auth": ^1.7.1 + "@azure/core-rest-pipeline": ^1.15.1 + "@azure/core-tracing": ^1.1.1 + "@azure/core-util": ^1.8.1 + fast-json-stable-stringify: ^2.1.0 + jsbi: ^4.3.0 + priorityqueuejs: ^2.0.0 + semaphore: ^1.1.0 + tslib: ^2.6.2 + checksum: b571f5a99b12520a2128b8ed0eb61cd66c432e21f533e778cd54a508e89b8bd57e8e05eedc1dcfdb4417c91a675bdb63d6c1cfcd9a21895d444e51de80288f33 + languageName: node + linkType: hard + +"@azure/logger@npm:^1.0.0": + version: 1.1.4 + resolution: "@azure/logger@npm:1.1.4" + dependencies: + tslib: ^2.6.2 + checksum: d4bfd83f31afc465689e02ac2d8eb0a1c6573cc47ea3fa18778c5d7d096ee7a4fdc130f00e9d162ec8ed192aeb9a54d5c3ab15bd7a12bbe039d5f594ba0f797b + languageName: node + linkType: hard + "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.24.7, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.2, @babel/code-frame@npm:^7.8.3": version: 7.26.2 resolution: "@babel/code-frame@npm:7.26.2" @@ -3018,6 +3100,44 @@ __metadata: languageName: unknown linkType: soft +"@discordjs/collection@npm:^2.1.1": + version: 2.1.1 + resolution: "@discordjs/collection@npm:2.1.1" + checksum: 8c4cd75061b378a35dfa50c4403828b8e6d5d32934047d1d26e5a4fcc2c1b8135ebf74a6dd9ec61afcb4ec030d596b85da5463dc28cad084635cd184eb69c453 + languageName: node + linkType: hard + +"@discordjs/rest@npm:^2.3.0": + version: 2.4.3 + resolution: "@discordjs/rest@npm:2.4.3" + dependencies: + "@discordjs/collection": ^2.1.1 + "@discordjs/util": ^1.1.1 + "@sapphire/async-queue": ^1.5.3 + "@sapphire/snowflake": ^3.5.3 + "@vladfrangu/async_event_emitter": ^2.4.6 + discord-api-types: ^0.37.119 + magic-bytes.js: ^1.10.0 + tslib: ^2.6.3 + undici: 6.21.1 + checksum: 25b0b4461b0c0a31e49680a21d6985ebf139caedaa2c4ae4d27f84b8d16ae43fae6b2e0f850f95f12627852a61c73172dd602444fbe4f00354a119e1bc78287a + languageName: node + linkType: hard + +"@discordjs/util@npm:^1.1.1": + version: 1.1.1 + resolution: "@discordjs/util@npm:1.1.1" + checksum: 13f25aa2917de732bdd90e9cee9322b69c8c0a173206e2ce308f1bb177d4ce20a138efdb5b0ec5029a10ebbbde71d4c12ba51354b09db4b488e8de429c393fd4 + languageName: node + linkType: hard + +"@discoveryjs/json-ext@npm:^0.6.1": + version: 0.6.3 + resolution: "@discoveryjs/json-ext@npm:0.6.3" + checksum: 8305a5feb9bbaedbfdb91f938cb577f98c34cb432535dbc7af5e5df7f1cb3d1895f7a9ec0d956b5bd9e980e5b7f8cd36684c4c9ed219e6e556e0dfe367c4cb66 + languageName: node + linkType: hard + "@emotion/babel-plugin@npm:^11.12.0": version: 11.12.0 resolution: "@emotion/babel-plugin@npm:11.12.0" @@ -3810,7 +3930,7 @@ __metadata: languageName: node linkType: hard -"@internationalized/date@npm:^3.5.5, @internationalized/date@npm:^3.7.0": +"@internationalized/date@npm:^3.7.0": version: 3.7.0 resolution: "@internationalized/date@npm:3.7.0" dependencies: @@ -3829,7 +3949,7 @@ __metadata: languageName: node linkType: hard -"@internationalized/number@npm:^3.5.3, @internationalized/number@npm:^3.6.0": +"@internationalized/number@npm:^3.6.0": version: 3.6.0 resolution: "@internationalized/number@npm:3.6.0" dependencies: @@ -3838,7 +3958,7 @@ __metadata: languageName: node linkType: hard -"@internationalized/string@npm:^3.2.3, @internationalized/string@npm:^3.2.5": +"@internationalized/string@npm:^3.2.5": version: 3.2.5 resolution: "@internationalized/string@npm:3.2.5" dependencies: @@ -4318,6 +4438,100 @@ __metadata: languageName: node linkType: hard +"@llamaindex/cloud@npm:3.0.0": + version: 3.0.0 + resolution: "@llamaindex/cloud@npm:3.0.0" + peerDependencies: + "@llamaindex/core": 0.5.0 + "@llamaindex/env": 0.1.27 + checksum: 65fa90b4b59b4c723cab2ba1082501560be45ff61a31c7d949107dd80f3ccdd243e34482704c681ff19c7b2355cff39b63a040ef0c505f7c38190e049e557d2f + languageName: node + linkType: hard + +"@llamaindex/core@npm:0.5.0": + version: 0.5.0 + resolution: "@llamaindex/core@npm:0.5.0" + dependencies: + "@llamaindex/env": 0.1.27 + "@types/node": ^22.9.0 + magic-bytes.js: ^1.10.0 + zod: ^3.23.8 + zod-to-json-schema: ^3.23.3 + checksum: fd65a5a35300fecedbc903a18d5b006dfe81072a35e102dc53e6c8364c4cbb2c7ac558e6a613dd416fd7fc5d1be373f6d468f200b27b044ab52820010fb7ccf5 + languageName: node + linkType: hard + +"@llamaindex/env@npm:0.1.27": + version: 0.1.27 + resolution: "@llamaindex/env@npm:0.1.27" + peerDependencies: + "@aws-crypto/sha256-js": ^5.2.0 + "@huggingface/transformers": ^3.0.2 + gpt-tokenizer: ^2.5.0 + js-tiktoken: ^1.0.12 + pathe: ^1.1.2 + peerDependenciesMeta: + "@aws-crypto/sha256-js": + optional: true + "@huggingface/transformers": + optional: true + js-tiktoken: + optional: true + pathe: + optional: true + tiktoken: + optional: true + checksum: ad9d4d3bbf6584ea6b469e75b6acd5cf83bdc36b59ff78ae31ca6ba9229bed0ff11935c24135ee33462afc5320b47cccbc2acfd84d9606e3b5b3682d49a887ba + languageName: node + linkType: hard + +"@llamaindex/node-parser@npm:1.0.0": + version: 1.0.0 + resolution: "@llamaindex/node-parser@npm:1.0.0" + dependencies: + html-to-text: ^9.0.5 + peerDependencies: + "@llamaindex/core": 0.5.0 + "@llamaindex/env": 0.1.27 + tree-sitter: ^0.22.0 + web-tree-sitter: ^0.24.3 + checksum: 5b7c45d8d8d2888142c4365e4660d55c6e3ec09c75cfa328a9f4a7a5548b55778aff97223f64da903e9ea97b181d0b72f7269e64555734126082b75638449a30 + languageName: node + linkType: hard + +"@llamaindex/openai@npm:0.1.52": + version: 0.1.52 + resolution: "@llamaindex/openai@npm:0.1.52" + dependencies: + "@llamaindex/core": 0.5.0 + "@llamaindex/env": 0.1.27 + openai: ^4.83.0 + checksum: fdfa30e5178c2c6951429a3e5581c427da8d3822fa9a06215dff6dfb29ea8d38a69d1a4c7f0d3b12bafa7b226bf2ccfadd45d8d1aadecf87c110eed9c3670176 + languageName: node + linkType: hard + +"@llamaindex/readers@npm:2.0.0": + version: 2.0.0 + resolution: "@llamaindex/readers@npm:2.0.0" + dependencies: + "@azure/cosmos": ^4.1.1 + "@discordjs/rest": ^2.3.0 + "@discoveryjs/json-ext": ^0.6.1 + assemblyai: ^4.8.0 + csv-parse: ^5.5.6 + discord-api-types: ^0.37.105 + mammoth: ^1.7.2 + mongodb: ^6.7.0 + notion-md-crawler: ^1.0.0 + papaparse: ^5.4.1 + unpdf: ^0.12.1 + peerDependencies: + "@llamaindex/core": 0.5.0 + "@llamaindex/env": 0.1.27 + checksum: d29396a37ac3ad902f39347fe2b4283c961a7ba9f26be13d1383faddd8d6c9778896e71a60a2c93ab4805b899eb162d31ae7f34f3c8c031b3d6abf152ddaaf23 + languageName: node + linkType: hard + "@lukeed/csprng@npm:^1.1.0": version: 1.1.0 resolution: "@lukeed/csprng@npm:1.1.0" @@ -4352,6 +4566,25 @@ __metadata: languageName: node linkType: hard +"@mapbox/node-pre-gyp@npm:^1.0.0": + version: 1.0.11 + resolution: "@mapbox/node-pre-gyp@npm:1.0.11" + dependencies: + detect-libc: ^2.0.0 + https-proxy-agent: ^5.0.0 + make-dir: ^3.1.0 + node-fetch: ^2.6.7 + nopt: ^5.0.0 + npmlog: ^5.0.1 + rimraf: ^3.0.2 + semver: ^7.3.5 + tar: ^6.1.11 + bin: + node-pre-gyp: bin/node-pre-gyp + checksum: b848f6abc531a11961d780db813cc510ca5a5b6bf3184d72134089c6875a91c44d571ba6c1879470020803f7803609e7b2e6e429651c026fe202facd11d444b8 + languageName: node + linkType: hard + "@mdx-js/react@npm:^3.0.0": version: 3.0.1 resolution: "@mdx-js/react@npm:3.0.1" @@ -4364,12 +4597,12 @@ __metadata: languageName: node linkType: hard -"@mongodb-js/saslprep@npm:^1.1.0": - version: 1.1.9 - resolution: "@mongodb-js/saslprep@npm:1.1.9" +"@mongodb-js/saslprep@npm:^1.1.0, @mongodb-js/saslprep@npm:^1.1.9": + version: 1.2.0 + resolution: "@mongodb-js/saslprep@npm:1.2.0" dependencies: sparse-bitfield: ^3.0.3 - checksum: 6f13983e41c9fbd5273eeae9135e47e5b7a19125a63287bea69e33a618f8e034cfcf2258c77d0f5d6dcf386dfe2bb520bc01613afd1528c52f82c71172629242 + checksum: a2df7bf5fde7c0a46fb0022208720ec8235dfaad0ed078200af16d123b8fa63c03083a7e086045d2d7e9ce7a5602e7766064c415c21406e9f176767802fae715 languageName: node linkType: hard @@ -4422,6 +4655,16 @@ __metadata: languageName: node linkType: hard +"@notionhq/client@npm:^2.2.15": + version: 2.2.16 + resolution: "@notionhq/client@npm:2.2.16" + dependencies: + "@types/node-fetch": ^2.5.10 + node-fetch: ^2.6.1 + checksum: f148ac1ae1b049d3076f685b93a98bbf8e41c08453a163bf50466b3f5ded3b5394eb07747107b1bb614679eefb83f515827a2b42c127579377e399d4e772c85c + languageName: node + linkType: hard + "@npmcli/fs@npm:^2.1.0": version: 2.1.2 resolution: "@npmcli/fs@npm:2.1.2" @@ -6236,211 +6479,255 @@ __metadata: languageName: node linkType: hard -"@react-aria/breadcrumbs@npm:^3.5.16": - version: 3.5.16 - resolution: "@react-aria/breadcrumbs@npm:3.5.16" +"@react-aria/autocomplete@npm:3.0.0-alpha.37": + version: 3.0.0-alpha.37 + resolution: "@react-aria/autocomplete@npm:3.0.0-alpha.37" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/link": ^3.7.4 - "@react-aria/utils": ^3.25.2 - "@react-types/breadcrumbs": ^3.7.7 - "@react-types/shared": ^3.24.1 + "@react-aria/combobox": ^3.11.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/listbox": ^3.14.0 + "@react-aria/searchfield": ^3.8.0 + "@react-aria/textfield": ^3.16.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/autocomplete": 3.0.0-alpha.0 + "@react-stately/combobox": ^3.10.2 + "@react-types/autocomplete": 3.0.0-alpha.28 + "@react-types/button": ^3.10.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: f0e8aa9401930a343c8814d809fe4fa9b7395c96024f9e5312c573a65492ddeb03558133c7957d88fc1914494412f1902eb640743686bc0a4fdb3e2505adb502 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 2ad7ef91cda86a66363c2d224680d3811e3db1e57f0f934ce5ffec3346bde2dbdd19fed5f93b0330de852271228758394caf220fda9006e0912ffe7c74849934 languageName: node linkType: hard -"@react-aria/button@npm:^3.9.8": - version: 3.9.8 - resolution: "@react-aria/button@npm:3.9.8" +"@react-aria/breadcrumbs@npm:^3.5.20": + version: 3.5.20 + resolution: "@react-aria/breadcrumbs@npm:3.5.20" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-stately/toggle": ^3.7.7 - "@react-types/button": ^3.9.6 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/link": ^3.7.8 + "@react-aria/utils": ^3.27.0 + "@react-types/breadcrumbs": ^3.7.10 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 0a651b2cbf3d71e2a862ce97fcb729bb97a1f891b73546484b2cc98c3a012a2d217842032320b6ca473a4957b56063151ac4a03164aa22cb0d65883eaf84bb40 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 76ac8ffb5b1d548d941aad7772297365fbd20e392341e9bc58fcd921b222c99b9783ca00ccf211f5a50d67d3a047c54bac5fa47c6951d3a483d2a0c0e1bef3eb languageName: node linkType: hard -"@react-aria/calendar@npm:^3.5.11": - version: 3.5.11 - resolution: "@react-aria/calendar@npm:3.5.11" +"@react-aria/button@npm:^3.11.1": + version: 3.11.1 + resolution: "@react-aria/button@npm:3.11.1" dependencies: - "@internationalized/date": ^3.5.5 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/live-announcer": ^3.3.4 - "@react-aria/utils": ^3.25.2 - "@react-stately/calendar": ^3.5.4 - "@react-types/button": ^3.9.6 - "@react-types/calendar": ^3.4.9 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/toolbar": 3.0.0-beta.12 + "@react-aria/utils": ^3.27.0 + "@react-stately/toggle": ^3.8.1 + "@react-types/button": ^3.10.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 79c4ee5bf233108c3f394f25bacf9190a452176b833a32f028acb38546be691a748248bab1bcf200b9eb7259baace0c6f0a398261f200bfa7a6df3f24cf6b3eb + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 402a3cf0f6d629ae6e3af973a791cf1ad8ebb0ce1b878e2319064cf51272987af8b69f9716c302ddd871bc8291156c53c4d7a59a42ba8aec247667fec6a8a493 languageName: node linkType: hard -"@react-aria/checkbox@npm:^3.14.6, @react-aria/checkbox@npm:^3.7.1": - version: 3.14.6 - resolution: "@react-aria/checkbox@npm:3.14.6" +"@react-aria/calendar@npm:^3.7.0": + version: 3.7.0 + resolution: "@react-aria/calendar@npm:3.7.0" dependencies: - "@react-aria/form": ^3.0.8 - "@react-aria/interactions": ^3.22.2 - "@react-aria/label": ^3.7.11 - "@react-aria/toggle": ^3.10.7 - "@react-aria/utils": ^3.25.2 - "@react-stately/checkbox": ^3.6.8 - "@react-stately/form": ^3.0.5 - "@react-stately/toggle": ^3.7.7 - "@react-types/checkbox": ^3.8.3 - "@react-types/shared": ^3.24.1 + "@internationalized/date": ^3.7.0 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/live-announcer": ^3.4.1 + "@react-aria/utils": ^3.27.0 + "@react-stately/calendar": ^3.7.0 + "@react-types/button": ^3.10.2 + "@react-types/calendar": ^3.6.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 138979484331c5d1e6693e42e34841a30ae281166cf8ccde53cf37ec07be6326ce0ad64478b92b177d3236f86eb8348552d1584d0875261eefddbcc9e5d63366 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 37f6f1461d132d4bef45149ad316f6830bb9bc3d4cd92f791415c416489f1bc4d07b84d3cb8e1e4515f8b07c8763bfdf17aae46a5a4f9e06e57244eaa4b7b7b5 languageName: node linkType: hard -"@react-aria/collections@npm:3.0.0-alpha.4": - version: 3.0.0-alpha.4 - resolution: "@react-aria/collections@npm:3.0.0-alpha.4" +"@react-aria/checkbox@npm:^3.15.1, @react-aria/checkbox@npm:^3.7.1": + version: 3.15.1 + resolution: "@react-aria/checkbox@npm:3.15.1" dependencies: - "@react-aria/ssr": ^3.9.5 - "@react-aria/utils": ^3.25.2 - "@react-types/shared": ^3.24.1 + "@react-aria/form": ^3.0.12 + "@react-aria/interactions": ^3.23.0 + "@react-aria/label": ^3.7.14 + "@react-aria/toggle": ^3.10.11 + "@react-aria/utils": ^3.27.0 + "@react-stately/checkbox": ^3.6.11 + "@react-stately/form": ^3.1.1 + "@react-stately/toggle": ^3.8.1 + "@react-types/checkbox": ^3.9.1 + "@react-types/shared": ^3.27.0 + "@swc/helpers": ^0.5.0 + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 3ebecaf0acd81bed0b78bd9bb34b91e2c848339699f7aec364478be6c6aee36a24c102c9a341239fe5a024fea520e6a9387889d2edae007a33feb98fa08d4dc3 + languageName: node + linkType: hard + +"@react-aria/collections@npm:3.0.0-alpha.7": + version: 3.0.0-alpha.7 + resolution: "@react-aria/collections@npm:3.0.0-alpha.7" + dependencies: + "@react-aria/ssr": ^3.9.7 + "@react-aria/utils": ^3.27.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 use-sync-external-store: ^1.2.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: dad3655789d80efd1f6a89700d0c2cbcb8930125bcf47077b764b002080b3c93abeed7b7b130e17126af3049a193dd35f50f9b11e1621a51afa12288ad822315 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 3424575a1bced8abd749781d0ba8f2eff16e86ce9d17fefb2344d79b26ef5b1d11a5d58318d7e6d6d841b8eba5d67e20627494f65cf3ec92f9fd0369d175b076 languageName: node linkType: hard -"@react-aria/color@npm:3.0.0-rc.2": - version: 3.0.0-rc.2 - resolution: "@react-aria/color@npm:3.0.0-rc.2" +"@react-aria/color@npm:^3.0.3": + version: 3.0.3 + resolution: "@react-aria/color@npm:3.0.3" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/numberfield": ^3.11.6 - "@react-aria/slider": ^3.7.11 - "@react-aria/spinbutton": ^3.6.8 - "@react-aria/textfield": ^3.14.8 - "@react-aria/utils": ^3.25.2 - "@react-aria/visually-hidden": ^3.8.15 - "@react-stately/color": ^3.7.2 - "@react-stately/form": ^3.0.5 - "@react-types/color": 3.0.0-rc.1 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/numberfield": ^3.11.10 + "@react-aria/slider": ^3.7.15 + "@react-aria/spinbutton": ^3.6.11 + "@react-aria/textfield": ^3.16.0 + "@react-aria/utils": ^3.27.0 + "@react-aria/visually-hidden": ^3.8.19 + "@react-stately/color": ^3.8.2 + "@react-stately/form": ^3.1.1 + "@react-types/color": ^3.0.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 07770e5cccdaef96b4a3c36c206f174eb3e9e2eb1cc5400e32a3746d1b556a0372a57eeff6d4efee54f855b9727f651d53e13dd8bf999581725b25cdb12891fd + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: e8b3b7be7c88b540e45bec981718f44b33a6646d837b5f8b3599028d778e781c1555390400508688a74b3514b6bed7e1e7e361358e67761af153e24c1a4aab3f languageName: node linkType: hard -"@react-aria/combobox@npm:^3.10.3": - version: 3.10.3 - resolution: "@react-aria/combobox@npm:3.10.3" +"@react-aria/combobox@npm:^3.11.1": + version: 3.11.1 + resolution: "@react-aria/combobox@npm:3.11.1" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/listbox": ^3.13.3 - "@react-aria/live-announcer": ^3.3.4 - "@react-aria/menu": ^3.15.3 - "@react-aria/overlays": ^3.23.2 - "@react-aria/selection": ^3.19.3 - "@react-aria/textfield": ^3.14.8 - "@react-aria/utils": ^3.25.2 - "@react-stately/collections": ^3.10.9 - "@react-stately/combobox": ^3.9.2 - "@react-stately/form": ^3.0.5 - "@react-types/button": ^3.9.6 - "@react-types/combobox": ^3.12.1 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/listbox": ^3.14.0 + "@react-aria/live-announcer": ^3.4.1 + "@react-aria/menu": ^3.17.0 + "@react-aria/overlays": ^3.25.0 + "@react-aria/selection": ^3.22.0 + "@react-aria/textfield": ^3.16.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/collections": ^3.12.1 + "@react-stately/combobox": ^3.10.2 + "@react-stately/form": ^3.1.1 + "@react-types/button": ^3.10.2 + "@react-types/combobox": ^3.13.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 3ca74b7ebaf29de21402816e497b378cb0a98efa86324d324217d49ded5cb938f356f855e31e414a904fd6956482c096e75a6a4cb68ca059e7a736299aede439 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 4ce4f77d8af54abde02c34780f90110806be2665a2c2c6ad16b4895998ef6e9fed16c2296888818f60b595827357641b60604e7a9148c716c16aa06ba1f36161 languageName: node linkType: hard -"@react-aria/datepicker@npm:^3.11.2": - version: 3.11.2 - resolution: "@react-aria/datepicker@npm:3.11.2" +"@react-aria/datepicker@npm:^3.13.0": + version: 3.13.0 + resolution: "@react-aria/datepicker@npm:3.13.0" dependencies: - "@internationalized/date": ^3.5.5 - "@internationalized/number": ^3.5.3 - "@internationalized/string": ^3.2.3 - "@react-aria/focus": ^3.18.2 - "@react-aria/form": ^3.0.8 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/label": ^3.7.11 - "@react-aria/spinbutton": ^3.6.8 - "@react-aria/utils": ^3.25.2 - "@react-stately/datepicker": ^3.10.2 - "@react-stately/form": ^3.0.5 - "@react-types/button": ^3.9.6 - "@react-types/calendar": ^3.4.9 - "@react-types/datepicker": ^3.8.2 - "@react-types/dialog": ^3.5.12 - "@react-types/shared": ^3.24.1 + "@internationalized/date": ^3.7.0 + "@internationalized/number": ^3.6.0 + "@internationalized/string": ^3.2.5 + "@react-aria/focus": ^3.19.1 + "@react-aria/form": ^3.0.12 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/label": ^3.7.14 + "@react-aria/spinbutton": ^3.6.11 + "@react-aria/utils": ^3.27.0 + "@react-stately/datepicker": ^3.12.0 + "@react-stately/form": ^3.1.1 + "@react-types/button": ^3.10.2 + "@react-types/calendar": ^3.6.0 + "@react-types/datepicker": ^3.10.0 + "@react-types/dialog": ^3.5.15 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 28267e6c977e8d80c81b9251e0fa641539890f8dd916a11dbbceac1672c8d03ea39af713f25b080cbc17d0c504f2fa996b9f91d12c12b3d10f44aa4d89b4363e + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: f5a551569d6bf2c067cb0f46477d45863943f8cb212a5a54ecdca5c59b33535a617a9fd36b408261f4b4c66d1889851bff795c516c7822f5a152a56c415e870e languageName: node linkType: hard -"@react-aria/dialog@npm:^3.5.17": - version: 3.5.17 - resolution: "@react-aria/dialog@npm:3.5.17" +"@react-aria/dialog@npm:^3.5.21": + version: 3.5.21 + resolution: "@react-aria/dialog@npm:3.5.21" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/overlays": ^3.23.2 - "@react-aria/utils": ^3.25.2 - "@react-types/dialog": ^3.5.12 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/overlays": ^3.25.0 + "@react-aria/utils": ^3.27.0 + "@react-types/dialog": ^3.5.15 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 2a43a973ea3d0237cca34b03208454564be34da5b0ff5d7527d392378db6d870986f285c901378534b6e0b51bd140d492e38a6f9cd3f12a6e357ddf1ba9141b9 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: e3237d64f19161af237deaacbfbbeeea4b12a7ec79aef2942e900e439891b0412e7651a2ec11bff35f9e71f2c1d01c3b792c343763a417b456539838b6683fe9 languageName: node linkType: hard -"@react-aria/dnd@npm:^3.7.2": - version: 3.7.2 - resolution: "@react-aria/dnd@npm:3.7.2" +"@react-aria/disclosure@npm:^3.0.1": + version: 3.0.1 + resolution: "@react-aria/disclosure@npm:3.0.1" dependencies: - "@internationalized/string": ^3.2.3 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/live-announcer": ^3.3.4 - "@react-aria/overlays": ^3.23.2 - "@react-aria/utils": ^3.25.2 - "@react-stately/dnd": ^3.4.2 - "@react-types/button": ^3.9.6 - "@react-types/shared": ^3.24.1 + "@react-aria/ssr": ^3.9.7 + "@react-aria/utils": ^3.27.0 + "@react-stately/disclosure": ^3.0.1 + "@react-types/button": ^3.10.2 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 265a2f6b708d5bd76ad0b1e1d29a04b90c2002f93eef0a021c220678013d6144daf6471f783e0d773bf6b955247b5df9ad63163351869ce8927942cdfd7b76a5 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 36e2178944270d6ca7c439e960b14509f6bdd19e6db059e298acd6f6c0b3760f81dcdb916eb8acb35877cb0db238d4aa839735d230721fe31d6eb077b6772b59 + languageName: node + linkType: hard + +"@react-aria/dnd@npm:^3.8.1": + version: 3.8.1 + resolution: "@react-aria/dnd@npm:3.8.1" + dependencies: + "@internationalized/string": ^3.2.5 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/live-announcer": ^3.4.1 + "@react-aria/overlays": ^3.25.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/dnd": ^3.5.1 + "@react-types/button": ^3.10.2 + "@react-types/shared": ^3.27.0 + "@swc/helpers": ^0.5.0 + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: c70cf246c6b7f3219a9f73473820f47199eb99221cb57a33cfc6263c8a97f7d09765ad76ad708c0848be5cb08cbce2edfddcd775324f159f63e9404f0b088b4a languageName: node linkType: hard @@ -6460,64 +6747,65 @@ __metadata: languageName: node linkType: hard -"@react-aria/form@npm:^3.0.8": - version: 3.0.8 - resolution: "@react-aria/form@npm:3.0.8" +"@react-aria/form@npm:^3.0.12": + version: 3.0.12 + resolution: "@react-aria/form@npm:3.0.12" dependencies: - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-stately/form": ^3.0.5 - "@react-types/shared": ^3.24.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/form": ^3.1.1 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 7e23ba71809e1acb9bc0e169bcf00583f970a88bcc84fe47e1b16c7478318d09201c2f6e2d508e6d9a1250ee41ebf812d0b2c8aa0b0960d9dcb08b8965eff770 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 8b4123f4b2cb7d8bfe19e3c1c1b931987d3500930c9d812f32f0518c5645c6d9221cb5d0d03153058fc1c7eb5c17167b99a8ecdf5895d6d8a0ab1e312a5dfe71 languageName: node linkType: hard -"@react-aria/grid@npm:^3.10.3": - version: 3.10.3 - resolution: "@react-aria/grid@npm:3.10.3" +"@react-aria/grid@npm:^3.11.1": + version: 3.11.1 + resolution: "@react-aria/grid@npm:3.11.1" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/live-announcer": ^3.3.4 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-stately/collections": ^3.10.9 - "@react-stately/grid": ^3.9.2 - "@react-stately/selection": ^3.16.2 - "@react-types/checkbox": ^3.8.3 - "@react-types/grid": ^3.2.8 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/live-announcer": ^3.4.1 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/collections": ^3.12.1 + "@react-stately/grid": ^3.10.1 + "@react-stately/selection": ^3.19.0 + "@react-types/checkbox": ^3.9.1 + "@react-types/grid": ^3.2.11 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 23fdf18fc08be6846f924a812a75ba7ed41e519e285d65b6f0ad8474de1d403e09999e115d303cfbac96112e3b47ae3177c76988ed0b252cdd15af5b5dc23b42 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: e8a3a8eee1472ee54abf5a46f5b098b49b0f1b72134db3bd13d3e67941db17bb6bd549a219287b670f9bf41b2fcac9ce239a63801414747013ae4a11989deb3c languageName: node linkType: hard -"@react-aria/gridlist@npm:^3.9.3": - version: 3.9.3 - resolution: "@react-aria/gridlist@npm:3.9.3" +"@react-aria/gridlist@npm:^3.10.1": + version: 3.10.1 + resolution: "@react-aria/gridlist@npm:3.10.1" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/grid": ^3.10.3 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-stately/collections": ^3.10.9 - "@react-stately/list": ^3.10.8 - "@react-stately/tree": ^3.8.4 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/grid": ^3.11.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/collections": ^3.12.1 + "@react-stately/list": ^3.11.2 + "@react-stately/tree": ^3.8.7 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 6091ac61fde8010d7e265b33c1742aee4c213bf3abc08ddbf1acba11e9f25ee94a5d3cf3810ee08f68cffbb4711fe25b8dbb4268e57bb67105058e42eb7e20a2 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: af0a6b3a77d588ae6705997e28376b1a21cb5049bcd542ac420c5868878d7416e05dc9f494f13ce03af81527fe2640861a3a2334ff8c3b81e49d14e7b77ea359 languageName: node linkType: hard @@ -6540,7 +6828,7 @@ __metadata: languageName: node linkType: hard -"@react-aria/interactions@npm:^3.14.0, @react-aria/interactions@npm:^3.22.2, @react-aria/interactions@npm:^3.23.0": +"@react-aria/interactions@npm:^3.14.0, @react-aria/interactions@npm:^3.23.0": version: 3.23.0 resolution: "@react-aria/interactions@npm:3.23.0" dependencies: @@ -6555,7 +6843,7 @@ __metadata: languageName: node linkType: hard -"@react-aria/label@npm:^3.7.11, @react-aria/label@npm:^3.7.14": +"@react-aria/label@npm:^3.7.14": version: 3.7.14 resolution: "@react-aria/label@npm:3.7.14" dependencies: @@ -6569,244 +6857,250 @@ __metadata: languageName: node linkType: hard -"@react-aria/link@npm:^3.3.6, @react-aria/link@npm:^3.7.4": - version: 3.7.4 - resolution: "@react-aria/link@npm:3.7.4" +"@react-aria/link@npm:^3.3.6, @react-aria/link@npm:^3.7.8": + version: 3.7.8 + resolution: "@react-aria/link@npm:3.7.8" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-types/link": ^3.5.7 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/utils": ^3.27.0 + "@react-types/link": ^3.5.10 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: ade14a7640d7e54571244b8d6bd4f7e177d7fe647e2819436a09aeaa0428a841f75c16c09f93c25aa18d1b8c99fba9f48accecbdc94f39183cff05771c91eaad + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: f10531feaafe35a1087adf68d090124eb801b237fcdd47ae96a66a5e932f9249ae604debc8e321bd9ca1613da4fa4e3aa9800e480cc4f4eea3d255114beae655 languageName: node linkType: hard -"@react-aria/listbox@npm:^3.13.3": - version: 3.13.3 - resolution: "@react-aria/listbox@npm:3.13.3" +"@react-aria/listbox@npm:^3.14.0": + version: 3.14.0 + resolution: "@react-aria/listbox@npm:3.14.0" dependencies: - "@react-aria/interactions": ^3.22.2 - "@react-aria/label": ^3.7.11 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-stately/collections": ^3.10.9 - "@react-stately/list": ^3.10.8 - "@react-types/listbox": ^3.5.1 - "@react-types/shared": ^3.24.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/label": ^3.7.14 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/collections": ^3.12.1 + "@react-stately/list": ^3.11.2 + "@react-types/listbox": ^3.5.4 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: ff1a386d185ddd1e4627ec9fef117d62a6e57767518e6f610ea5f5d3b250a44b370f53445bf4b173c580138258a4e42f6114b6930eac234635a6832486d24c21 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 17c5de40b7f499249ec58fc66c40c2dccf789da4da9b5a158430bff687dcd95e77e098a0cc5b8b2a8fcbfcb300a97f37bcf4aaa3a4870e561507fc2b4e06e68c languageName: node linkType: hard -"@react-aria/live-announcer@npm:^3.3.4": - version: 3.3.4 - resolution: "@react-aria/live-announcer@npm:3.3.4" +"@react-aria/live-announcer@npm:^3.4.1": + version: 3.4.1 + resolution: "@react-aria/live-announcer@npm:3.4.1" dependencies: "@swc/helpers": ^0.5.0 - checksum: f216c6049ea77bcecec17cfbb1453e59b2b6034aa03edc6e9df74ab162a1f4197e7b07fb71b086a3b074981ef3171706f7fec4b9877901b7243c16321696a64c + checksum: 8f8416c30e359729683e05836b66234cb4156f6166bf6ba023bc0fd4408f2679bac59bd8e6639b629e438b2da292839aa8c293575ad30499f95ea650fccf8a1a languageName: node linkType: hard -"@react-aria/menu@npm:^3.15.3": - version: 3.15.3 - resolution: "@react-aria/menu@npm:3.15.3" +"@react-aria/menu@npm:^3.17.0": + version: 3.17.0 + resolution: "@react-aria/menu@npm:3.17.0" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/overlays": ^3.23.2 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-stately/collections": ^3.10.9 - "@react-stately/menu": ^3.8.2 - "@react-stately/tree": ^3.8.4 - "@react-types/button": ^3.9.6 - "@react-types/menu": ^3.9.11 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/overlays": ^3.25.0 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/collections": ^3.12.1 + "@react-stately/menu": ^3.9.1 + "@react-stately/selection": ^3.19.0 + "@react-stately/tree": ^3.8.7 + "@react-types/button": ^3.10.2 + "@react-types/menu": ^3.9.14 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 1d43336681960dc4b6c83e1a74c8704c192481df5ad0103f6992d1ebdc7b7cf56aa3d99c969bc3b9fbae571eec8b1274edfce46309d72b100fda5ca0dbc8343e + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 78b0573a498fe2bbf40c73cdb8bd8d3cf97e1ddb3e783fb2a4160e997c94827aa6ad76f4fc2f7d552e14df845606e91d6bf7f417c2098f13f99b6581d8e09e55 languageName: node linkType: hard -"@react-aria/meter@npm:^3.4.16": - version: 3.4.16 - resolution: "@react-aria/meter@npm:3.4.16" +"@react-aria/meter@npm:^3.4.19": + version: 3.4.19 + resolution: "@react-aria/meter@npm:3.4.19" dependencies: - "@react-aria/progress": ^3.4.16 - "@react-types/meter": ^3.4.3 - "@react-types/shared": ^3.24.1 + "@react-aria/progress": ^3.4.19 + "@react-types/meter": ^3.4.6 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 36dcff44b9493ea93eb278f69afb1248a2352efc8cd0b7458e72924205f6c0290b5727dee587ce6675de17bb23b08baf0567043ae0629cb42ba72c197d50d5d6 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 90fc867419360196eeb005a97de245b573a112690dfe6332ab9c037ae993f01220d3c6fe41562607ed08c08f278e010c62701a77041126e7ac2d2618096a63c7 languageName: node linkType: hard -"@react-aria/numberfield@npm:^3.11.6": - version: 3.11.6 - resolution: "@react-aria/numberfield@npm:3.11.6" +"@react-aria/numberfield@npm:^3.11.10": + version: 3.11.10 + resolution: "@react-aria/numberfield@npm:3.11.10" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/spinbutton": ^3.6.8 - "@react-aria/textfield": ^3.14.8 - "@react-aria/utils": ^3.25.2 - "@react-stately/form": ^3.0.5 - "@react-stately/numberfield": ^3.9.6 - "@react-types/button": ^3.9.6 - "@react-types/numberfield": ^3.8.5 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/spinbutton": ^3.6.11 + "@react-aria/textfield": ^3.16.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/form": ^3.1.1 + "@react-stately/numberfield": ^3.9.9 + "@react-types/button": ^3.10.2 + "@react-types/numberfield": ^3.8.8 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 8ca444e995842371d95c22824f8e9e1405a1602ce0d5b9379a3f31d83b6752ce2dca7d81e7aa418b1c14a0ea178b0f2dc8b4ed88e9533f4399ff29b4171ccd8a + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 05bf84defd45590e8f60be56d2778cb9defed2a8e57fd0a45a80a02625f81ed5aa57859b300883093947a73e76f58e2dce3a49b6b6155de85792105863c08517 languageName: node linkType: hard -"@react-aria/overlays@npm:^3.23.2": - version: 3.23.2 - resolution: "@react-aria/overlays@npm:3.23.2" +"@react-aria/overlays@npm:^3.25.0": + version: 3.25.0 + resolution: "@react-aria/overlays@npm:3.25.0" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/ssr": ^3.9.5 - "@react-aria/utils": ^3.25.2 - "@react-aria/visually-hidden": ^3.8.15 - "@react-stately/overlays": ^3.6.10 - "@react-types/button": ^3.9.6 - "@react-types/overlays": ^3.8.9 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/ssr": ^3.9.7 + "@react-aria/utils": ^3.27.0 + "@react-aria/visually-hidden": ^3.8.19 + "@react-stately/overlays": ^3.6.13 + "@react-types/button": ^3.10.2 + "@react-types/overlays": ^3.8.12 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: b7c82b241f4a3ce14a0602b105e0ed81e4d6bc0e6c85a151ac66ce5476e61ce1c74321739649933aa1bbebf5b537ad775ddd1cad58a41182b19a94d87e46fa66 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: d2a4646debad2fe9e607d38029eb0969ae58ed22cc2e02a2e01ee13b860cf30e32e121db2494e10460930961f6185db65f20e23d5301be0d7d605478b7fae658 languageName: node linkType: hard -"@react-aria/progress@npm:^3.4.16": - version: 3.4.16 - resolution: "@react-aria/progress@npm:3.4.16" +"@react-aria/progress@npm:^3.4.19": + version: 3.4.19 + resolution: "@react-aria/progress@npm:3.4.19" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/label": ^3.7.11 - "@react-aria/utils": ^3.25.2 - "@react-types/progress": ^3.5.6 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/label": ^3.7.14 + "@react-aria/utils": ^3.27.0 + "@react-types/progress": ^3.5.9 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 496d68df73dcbba35a0e144dce2bcd46622abb596ea22f686417db8a0baea51b1126189473688a5c1b3c727c21550cfc08526a4e20483c144f69e3f5fc69468b + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 4e0cc6761e5a08b7be8939e5534d43795c9b99feb8a583a77185640edcb4102afa8b5832fa54d08ae9e12821a6046c62c2f9c0aaad55ce4eb05fdc031ba3d904 languageName: node linkType: hard -"@react-aria/radio@npm:^3.10.7, @react-aria/radio@npm:^3.4.2": - version: 3.10.7 - resolution: "@react-aria/radio@npm:3.10.7" +"@react-aria/radio@npm:^3.10.11, @react-aria/radio@npm:^3.4.2": + version: 3.10.11 + resolution: "@react-aria/radio@npm:3.10.11" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/form": ^3.0.8 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/label": ^3.7.11 - "@react-aria/utils": ^3.25.2 - "@react-stately/radio": ^3.10.7 - "@react-types/radio": ^3.8.3 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/form": ^3.0.12 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/label": ^3.7.14 + "@react-aria/utils": ^3.27.0 + "@react-stately/radio": ^3.10.10 + "@react-types/radio": ^3.8.6 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: be98368900ffc67cc6f5d32536ad0ded2c7b07c0c58a27dd2dffd56d0c2d251bf9d52ed670edf3505a8041c44dbd644dafa6ce57cb5bbe38eb591d8daa9597d8 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 280fc7abc8dc34ded0b6a0cefdddb8326eb64c5fd6ababcc36171cdb099867f35ce8a4e7d3c55d6db154a8fab75d7de0008cb740fe33a4ff3b291ca8e2507e7d languageName: node linkType: hard -"@react-aria/searchfield@npm:^3.7.8": - version: 3.7.8 - resolution: "@react-aria/searchfield@npm:3.7.8" +"@react-aria/searchfield@npm:^3.8.0": + version: 3.8.0 + resolution: "@react-aria/searchfield@npm:3.8.0" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/textfield": ^3.14.8 - "@react-aria/utils": ^3.25.2 - "@react-stately/searchfield": ^3.5.6 - "@react-types/button": ^3.9.6 - "@react-types/searchfield": ^3.5.8 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/textfield": ^3.16.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/searchfield": ^3.5.9 + "@react-types/button": ^3.10.2 + "@react-types/searchfield": ^3.5.11 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 7e96bdcb608c717d29aeb6638c3c5f0a7eb2253b2488abbb4148594ea3dcdbfd0915ce38e2f7b998ee25e305c69ebc43aba9bcdbf31046d97ae0c078b179601e + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 41849c899d2189e5554866c21d10040a4e847f0bb863a549e37107fa264a7622787c9d0d2577173b1316d2bd40ac297c5d46a834587285b2bfeb4f9b02b7cb15 languageName: node linkType: hard -"@react-aria/select@npm:^3.14.9": - version: 3.14.9 - resolution: "@react-aria/select@npm:3.14.9" +"@react-aria/select@npm:^3.15.1": + version: 3.15.1 + resolution: "@react-aria/select@npm:3.15.1" dependencies: - "@react-aria/form": ^3.0.8 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/label": ^3.7.11 - "@react-aria/listbox": ^3.13.3 - "@react-aria/menu": ^3.15.3 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-aria/visually-hidden": ^3.8.15 - "@react-stately/select": ^3.6.7 - "@react-types/button": ^3.9.6 - "@react-types/select": ^3.9.6 - "@react-types/shared": ^3.24.1 + "@react-aria/form": ^3.0.12 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/label": ^3.7.14 + "@react-aria/listbox": ^3.14.0 + "@react-aria/menu": ^3.17.0 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-aria/visually-hidden": ^3.8.19 + "@react-stately/select": ^3.6.10 + "@react-types/button": ^3.10.2 + "@react-types/select": ^3.9.9 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 98f3935b56930f72838fc1e513fe0141f4ca221acd659ed9c72ed42db70b2deddef7086e96db2e61185cf68ceea5cf148141c7a7dd34656cdfa517d903032bdc + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 81dc71ac217089ee3c07cfae748fc081e563b4614a17bad29656bd4b1652bbf0c88d58cdd1e6c859bd57a1d3dd7f77b355ee4cff4ef3e95591e71d88e65d85c2 languageName: node linkType: hard -"@react-aria/selection@npm:^3.19.3": - version: 3.19.3 - resolution: "@react-aria/selection@npm:3.19.3" +"@react-aria/selection@npm:^3.22.0": + version: 3.22.0 + resolution: "@react-aria/selection@npm:3.22.0" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-stately/selection": ^3.16.2 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/selection": ^3.19.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: fa37f096476907cbf0583c6d544a31afa87c23b553a82b1563d36ea6bf59b19e5917423b2678ffd8961726525329b389108aff715711692cf1827cccfaff80d2 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 4e48d6343bceab1acdc7d4c9ba1a1d6dad400ad3fd0b8de55ea40b42cdc47aebcf7deb276179b14c07919a78f0c8ec13b671c3b4404d54a61570aadb29dd64b9 languageName: node linkType: hard -"@react-aria/separator@npm:^3.4.2": - version: 3.4.2 - resolution: "@react-aria/separator@npm:3.4.2" +"@react-aria/separator@npm:^3.4.5": + version: 3.4.5 + resolution: "@react-aria/separator@npm:3.4.5" dependencies: - "@react-aria/utils": ^3.25.2 - "@react-types/shared": ^3.24.1 + "@react-aria/utils": ^3.27.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: d6139a31dccffe2f8669c934287218bfa9127f268888d8f0d8f1482b7a58b6d034b3d5f7a92c812af28cb1d193b108b4e9e50c305647cd6278c7463e02a07a87 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: d67861b58dc55399b38a0e7387942f8a88a2fbdd3dc71e34a0e88bfb8e849c4a2afc3737dbbe12ad887fa54a8718dceb931bca2308ba604c376d4ae0afcd2f13 languageName: node linkType: hard -"@react-aria/slider@npm:^3.7.11, @react-aria/slider@npm:^3.7.15": +"@react-aria/slider@npm:^3.7.15": version: 3.7.15 resolution: "@react-aria/slider@npm:3.7.15" dependencies: @@ -6826,20 +7120,20 @@ __metadata: languageName: node linkType: hard -"@react-aria/spinbutton@npm:^3.6.8": - version: 3.6.8 - resolution: "@react-aria/spinbutton@npm:3.6.8" +"@react-aria/spinbutton@npm:^3.6.11": + version: 3.6.11 + resolution: "@react-aria/spinbutton@npm:3.6.11" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/live-announcer": ^3.3.4 - "@react-aria/utils": ^3.25.2 - "@react-types/button": ^3.9.6 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/live-announcer": ^3.4.1 + "@react-aria/utils": ^3.27.0 + "@react-types/button": ^3.10.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: fe626ccd30a9d52cb57ac3b0b5dd1d3f75157e2c93b39d9e60f5e050f8f8a6857959cb51cb1710405d915e7f2bb8c45c023685b6edd943455c475c7f10cb0f24 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 5b190fd5468bee752cf28471ea9d3baf52ebf5d8a0d8e374e00bc3ded3614427a209b7e090024b3a6e20dbb2a0e48e16661b79b9a4024acc1e59cf448871e007 languageName: node linkType: hard @@ -6854,171 +7148,175 @@ __metadata: languageName: node linkType: hard -"@react-aria/switch@npm:^3.3.1, @react-aria/switch@npm:^3.6.7": - version: 3.6.7 - resolution: "@react-aria/switch@npm:3.6.7" +"@react-aria/switch@npm:^3.3.1, @react-aria/switch@npm:^3.6.11": + version: 3.6.11 + resolution: "@react-aria/switch@npm:3.6.11" dependencies: - "@react-aria/toggle": ^3.10.7 - "@react-stately/toggle": ^3.7.7 - "@react-types/shared": ^3.24.1 - "@react-types/switch": ^3.5.5 + "@react-aria/toggle": ^3.10.11 + "@react-stately/toggle": ^3.8.1 + "@react-types/shared": ^3.27.0 + "@react-types/switch": ^3.5.8 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: d2c7ae260406d71df6edb2e7389b1af5c5ec19467894f261ced76d558467c084c1d85c22c2bccb1256faa65ce12f2286c9068d8727f749cf90ecc5701696c18d + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: ca35a48c72423e299547d4ad68e44653680880f0ad5f5fb6e9cbc30a1c8d4b0e249a2810f0e24e64ea671259e012a4f256b00c61891a087ea70a032fb5e054af languageName: node linkType: hard -"@react-aria/table@npm:^3.15.3": - version: 3.15.3 - resolution: "@react-aria/table@npm:3.15.3" +"@react-aria/table@npm:^3.16.1": + version: 3.16.1 + resolution: "@react-aria/table@npm:3.16.1" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/grid": ^3.10.3 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/live-announcer": ^3.3.4 - "@react-aria/utils": ^3.25.2 - "@react-aria/visually-hidden": ^3.8.15 - "@react-stately/collections": ^3.10.9 - "@react-stately/flags": ^3.0.3 - "@react-stately/table": ^3.12.2 - "@react-types/checkbox": ^3.8.3 - "@react-types/grid": ^3.2.8 - "@react-types/shared": ^3.24.1 - "@react-types/table": ^3.10.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/grid": ^3.11.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/live-announcer": ^3.4.1 + "@react-aria/utils": ^3.27.0 + "@react-aria/visually-hidden": ^3.8.19 + "@react-stately/collections": ^3.12.1 + "@react-stately/flags": ^3.0.5 + "@react-stately/table": ^3.13.1 + "@react-types/checkbox": ^3.9.1 + "@react-types/grid": ^3.2.11 + "@react-types/shared": ^3.27.0 + "@react-types/table": ^3.10.4 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 6be08ba40d2a6c7fce5fe3c11e3e9921dcbb2f1e451007f99f4f761d4562e5cbcd1de58db4cacbb31644ef6df95af00cadec782d17125bf68d80f78b06101446 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 6b0c484960433483e35df2bc89ead199d59b5bb38bae24f6e24fd0277f2cff74d626ec1cbba545bcc0e31e80af60da9f3d5de58c430dbe6b5eabf4a139ed2877 languageName: node linkType: hard -"@react-aria/tabs@npm:^3.9.5": - version: 3.9.5 - resolution: "@react-aria/tabs@npm:3.9.5" +"@react-aria/tabs@npm:^3.9.9": + version: 3.9.9 + resolution: "@react-aria/tabs@npm:3.9.9" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/i18n": ^3.12.2 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-stately/tabs": ^3.6.9 - "@react-types/shared": ^3.24.1 - "@react-types/tabs": ^3.3.9 + "@react-aria/focus": ^3.19.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/tabs": ^3.7.1 + "@react-types/shared": ^3.27.0 + "@react-types/tabs": ^3.3.12 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: ff3fe02826ab7808f2796301fe2766a0215c5266705f39fdd7e65b0b51cff3affcdb560cf44f1327ceadac6f4d75e9c59ac34bed721059debe196319dae92ba5 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 84826473fa7ddbd7590bef37692f2f99d8626f550e20d22ee23fa2b31bf670f78365bdf896dc6cdd8d77fd022413727ef5a4a7768ce005a1c122cba0f8b4e6b8 languageName: node linkType: hard -"@react-aria/tag@npm:^3.4.5": - version: 3.4.5 - resolution: "@react-aria/tag@npm:3.4.5" +"@react-aria/tag@npm:^3.4.9": + version: 3.4.9 + resolution: "@react-aria/tag@npm:3.4.9" dependencies: - "@react-aria/gridlist": ^3.9.3 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/label": ^3.7.11 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-stately/list": ^3.10.8 - "@react-types/button": ^3.9.6 - "@react-types/shared": ^3.24.1 + "@react-aria/gridlist": ^3.10.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/label": ^3.7.14 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/list": ^3.11.2 + "@react-types/button": ^3.10.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 5a876cadc90cd5de38cc2facd786bad602439739bc939ed6622bfb7a7b732b8c98008e71e93a2cb1114edb6bc8059876573fdeaad0beeba4f27bb27df0f830a9 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 9c6f8b8089f72281f23a62bfd2f722ddab9c7e8fe87cac415eb007ef34bbe5dfe7662ab3059a3628edc43b2fc106f9852fcbb818ac49351372318632ba382b4f languageName: node linkType: hard -"@react-aria/textfield@npm:^3.11.0, @react-aria/textfield@npm:^3.14.8, @react-aria/textfield@npm:^3.8.1": - version: 3.14.8 - resolution: "@react-aria/textfield@npm:3.14.8" +"@react-aria/textfield@npm:^3.11.0, @react-aria/textfield@npm:^3.16.0, @react-aria/textfield@npm:^3.8.1": + version: 3.16.0 + resolution: "@react-aria/textfield@npm:3.16.0" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/form": ^3.0.8 - "@react-aria/label": ^3.7.11 - "@react-aria/utils": ^3.25.2 - "@react-stately/form": ^3.0.5 - "@react-stately/utils": ^3.10.3 - "@react-types/shared": ^3.24.1 - "@react-types/textfield": ^3.9.6 + "@react-aria/focus": ^3.19.1 + "@react-aria/form": ^3.0.12 + "@react-aria/label": ^3.7.14 + "@react-aria/utils": ^3.27.0 + "@react-stately/form": ^3.1.1 + "@react-stately/utils": ^3.10.5 + "@react-types/shared": ^3.27.0 + "@react-types/textfield": ^3.11.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 861e865a23aa1598058aebd86676e12ffe6b0115520998709d1c983337377d73126d4802759fc1a03da9c2f2f30b6f37caff755c1fe82c649e47afe00fe3904d + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 3eeef777a1b50a044caf396c562f3a475ed348e7ccae452e6bd61cc89febeb05e7b9f39ccf8e46dc07398436eb94a438372ec45557db23ad01f07c88a36a57d7 languageName: node linkType: hard -"@react-aria/toggle@npm:^3.10.7": - version: 3.10.7 - resolution: "@react-aria/toggle@npm:3.10.7" +"@react-aria/toggle@npm:^3.10.11": + version: 3.10.11 + resolution: "@react-aria/toggle@npm:3.10.11" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-stately/toggle": ^3.7.7 - "@react-types/checkbox": ^3.8.3 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/toggle": ^3.8.1 + "@react-types/checkbox": ^3.9.1 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: c6ab18c046774a8865507dc85ff30a3d0931484d08bfc84ad2f024b9c78bbd0442fedfb0e5c99e74b08e62c95f66af6693c78e10f06520a0faf603b674c9fbf8 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 69e1240bb4f3f1c6b16b44f30bee7783834ccd9c23dd83d70564c7ca16d1030a86048d1008a8993e3964c361ff1c041a4a69f8ba682eaadfef808498d171434c languageName: node linkType: hard -"@react-aria/toolbar@npm:3.0.0-beta.8": - version: 3.0.0-beta.8 - resolution: "@react-aria/toolbar@npm:3.0.0-beta.8" +"@react-aria/toolbar@npm:3.0.0-beta.12": + version: 3.0.0-beta.12 + resolution: "@react-aria/toolbar@npm:3.0.0-beta.12" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/i18n": ^3.12.2 - "@react-aria/utils": ^3.25.2 - "@react-types/shared": ^3.24.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/utils": ^3.27.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: d54deabbcc0d574a7d681045c972b291ad9afed141414bb09c4358ed95b78a3a665c7ccf80d05525709d659c57fb02b2eb1e1759b8f556b439859c191e37dc0b + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 914bdd91dafe08088d5c23c8e76dc2554c07d13bddb8caea38ac20a9704e2559a455f401d7edb06e8aa79bc661ea124cd0b0301687cd88ef3932759ed7bdd3be languageName: node linkType: hard -"@react-aria/tooltip@npm:^3.7.7": - version: 3.7.7 - resolution: "@react-aria/tooltip@npm:3.7.7" +"@react-aria/tooltip@npm:^3.7.11": + version: 3.7.11 + resolution: "@react-aria/tooltip@npm:3.7.11" dependencies: - "@react-aria/focus": ^3.18.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-stately/tooltip": ^3.4.12 - "@react-types/shared": ^3.24.1 - "@react-types/tooltip": ^3.4.11 + "@react-aria/focus": ^3.19.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/tooltip": ^3.5.1 + "@react-types/shared": ^3.27.0 + "@react-types/tooltip": ^3.4.14 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: b1fba241a059100d8e9025d45611cd672b42ac7a895b5d8d6e6d7b91498d9180a314d7b5bd08d3f617cba8d10e62b1cdfc70f5470125fb9476037ce3c0eb8087 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 34d0e81b5c24119cc702742c1b41a74b1514513f13e2e0d671d0850565d10ae92c66129a24aa398a2853c868ef7a16e57742c442453683eeb092b5a6bc0934bf languageName: node linkType: hard -"@react-aria/tree@npm:3.0.0-alpha.5": - version: 3.0.0-alpha.5 - resolution: "@react-aria/tree@npm:3.0.0-alpha.5" +"@react-aria/tree@npm:3.0.0-beta.3": + version: 3.0.0-beta.3 + resolution: "@react-aria/tree@npm:3.0.0-beta.3" dependencies: - "@react-aria/gridlist": ^3.9.3 - "@react-aria/i18n": ^3.12.2 - "@react-aria/selection": ^3.19.3 - "@react-aria/utils": ^3.25.2 - "@react-stately/tree": ^3.8.4 - "@react-types/button": ^3.9.6 - "@react-types/shared": ^3.24.1 + "@react-aria/gridlist": ^3.10.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/selection": ^3.22.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/tree": ^3.8.7 + "@react-types/button": ^3.10.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 4471a33d58a19f69e1317c26e958559a48e39fadefe3febe92b117f4b0b07aaecae87a061426d464f9cb8096164dfc9d6dbd9ca8fa924bdec9006e72ab3eb92e + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: d020ce42d49f218187856644be39119521fc9a0c1fa29eee35ebf9ace8b3d7dcc17a4af6fb91edc505f1eabd09a48df5241272b5b5f53692f08485e9971f60ae languageName: node linkType: hard @@ -7038,34 +7336,35 @@ __metadata: languageName: node linkType: hard -"@react-aria/virtualizer@npm:^4.0.2": - version: 4.0.2 - resolution: "@react-aria/virtualizer@npm:4.0.2" +"@react-aria/virtualizer@npm:^4.1.1": + version: 4.1.1 + resolution: "@react-aria/virtualizer@npm:4.1.1" dependencies: - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-stately/virtualizer": ^4.0.2 - "@react-types/shared": ^3.24.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/utils": ^3.27.0 + "@react-stately/virtualizer": ^4.2.1 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: fb6f0073ee482930d5e89040a9ae9daa5a1d3c509ad92b27d1de3f4111405026c0efb7835c37327811f883ee5c38c5b0ada8c67d5d075640d1b0506f9296d430 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 7589e1d3491ae2cbb280c777be420ef588e0d4d00b003e56271fc091ba81ffc40b965f9c0f040e137949b081f42519b6dd48117d72c1a24262684af5eede2916 languageName: node linkType: hard -"@react-aria/visually-hidden@npm:^3.8.0, @react-aria/visually-hidden@npm:^3.8.15": - version: 3.8.15 - resolution: "@react-aria/visually-hidden@npm:3.8.15" +"@react-aria/visually-hidden@npm:^3.8.0, @react-aria/visually-hidden@npm:^3.8.19": + version: 3.8.19 + resolution: "@react-aria/visually-hidden@npm:3.8.19" dependencies: - "@react-aria/interactions": ^3.22.2 - "@react-aria/utils": ^3.25.2 - "@react-types/shared": ^3.24.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/utils": ^3.27.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 4263bad7aab2d95c508c69faa420e2f0e6ee0f8a34482fe50561406c8d4bce70e1bf6b30f1d55575111466e821993a43b942fcbd78e2ba381e90ebda6ae2a285 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 83085be588ce63114e6506f61fa6987521b4539a1c4e1c5912e18d2a2b8feaa962f90d1c1fa689158f95c9428136b63305f8ccee6426ff0b9a0504b804d64e8e languageName: node linkType: hard @@ -7303,299 +7602,323 @@ __metadata: languageName: node linkType: hard -"@react-stately/calendar@npm:^3.5.4": - version: 3.5.4 - resolution: "@react-stately/calendar@npm:3.5.4" +"@react-stately/autocomplete@npm:3.0.0-alpha.0": + version: 3.0.0-alpha.0 + resolution: "@react-stately/autocomplete@npm:3.0.0-alpha.0" dependencies: - "@internationalized/date": ^3.5.5 - "@react-stately/utils": ^3.10.3 - "@react-types/calendar": ^3.4.9 - "@react-types/shared": ^3.24.1 + "@react-stately/utils": ^3.10.4 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: c7b61066ee0b539b0d02c49ddf5582bc30861e7fe17aa280e84844446e0b51bfc0462f8e6b8f8eb92d228b01727165deb28ed8195fee3b5303397ca322d86014 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 43f48038dae1759871cfef40198b8b0bfd49f2b1869eb2407ce4d4f79745e6f302588f2081707b29a4c00926de77c0a14fd2ae16f93dc016669b652fc78516cd languageName: node linkType: hard -"@react-stately/checkbox@npm:^3.6.8": - version: 3.6.8 - resolution: "@react-stately/checkbox@npm:3.6.8" +"@react-stately/calendar@npm:^3.7.0": + version: 3.7.0 + resolution: "@react-stately/calendar@npm:3.7.0" dependencies: - "@react-stately/form": ^3.0.5 - "@react-stately/utils": ^3.10.3 - "@react-types/checkbox": ^3.8.3 - "@react-types/shared": ^3.24.1 + "@internationalized/date": ^3.7.0 + "@react-stately/utils": ^3.10.5 + "@react-types/calendar": ^3.6.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 1eae8160f8d393d8c7d4852634d87a62c4bdf3f53bb39fa9b1458d1cdb849f7d2386c8aae68a9a5d69c2916ea467e72343dfaeb839707ccbd5a45f2b8421c8b1 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: bb2048d159dca311fad1c09c3baef2ef4f2dd420e7f186f84681956d5ef11cc6cf55bd5aa76fb7d05f7f3a8210fc558a32820fef98d7cee7ac11c85dcf921bd0 languageName: node linkType: hard -"@react-stately/collections@npm:^3.10.9": - version: 3.10.9 - resolution: "@react-stately/collections@npm:3.10.9" +"@react-stately/checkbox@npm:^3.6.11": + version: 3.6.11 + resolution: "@react-stately/checkbox@npm:3.6.11" dependencies: - "@react-types/shared": ^3.24.1 + "@react-stately/form": ^3.1.1 + "@react-stately/utils": ^3.10.5 + "@react-types/checkbox": ^3.9.1 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 2e3a50cc687a353476bac7b0d4e0084a18993820404c9429c88ce14bd446e809b0117ab174c4f390c2348486e87971825c9cf9001e6810fba4593ef93dc91f54 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: aba17c9a3ae6ff08599f4219c3d28022bba0fb6f088261ccada4a187e89a6b6379987769ad9c7969850c194998b3c562e4104d727e54843809429f8e6f836346 languageName: node linkType: hard -"@react-stately/color@npm:^3.7.2": - version: 3.7.2 - resolution: "@react-stately/color@npm:3.7.2" +"@react-stately/collections@npm:^3.10.9, @react-stately/collections@npm:^3.12.1": + version: 3.12.1 + resolution: "@react-stately/collections@npm:3.12.1" dependencies: - "@internationalized/number": ^3.5.3 - "@internationalized/string": ^3.2.3 - "@react-aria/i18n": ^3.12.2 - "@react-stately/form": ^3.0.5 - "@react-stately/numberfield": ^3.9.6 - "@react-stately/slider": ^3.5.7 - "@react-stately/utils": ^3.10.3 - "@react-types/color": 3.0.0-rc.1 - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 40e31cb353c9c2d4b3da55ebf54260b861fadcceedd7742ed30232217c81bde1d5959e927e343fb54a3e2cf7c442e98a0be540abcc392c32fc81345f676f50b7 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: c835b8746fd49b830013fa9d7c2182d27aae41daeb9036c5eba96541241e14c651ebe8eb179c6cadab04070e9bc1e44d712c63a8f49bd97d1f2ba211a0b30b36 languageName: node linkType: hard -"@react-stately/combobox@npm:^3.9.2": - version: 3.9.2 - resolution: "@react-stately/combobox@npm:3.9.2" +"@react-stately/color@npm:^3.8.2": + version: 3.8.2 + resolution: "@react-stately/color@npm:3.8.2" dependencies: - "@react-stately/collections": ^3.10.9 - "@react-stately/form": ^3.0.5 - "@react-stately/list": ^3.10.8 - "@react-stately/overlays": ^3.6.10 - "@react-stately/select": ^3.6.7 - "@react-stately/utils": ^3.10.3 - "@react-types/combobox": ^3.12.1 - "@react-types/shared": ^3.24.1 + "@internationalized/number": ^3.6.0 + "@internationalized/string": ^3.2.5 + "@react-stately/form": ^3.1.1 + "@react-stately/numberfield": ^3.9.9 + "@react-stately/slider": ^3.6.1 + "@react-stately/utils": ^3.10.5 + "@react-types/color": ^3.0.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 7850479e673f0ba243cc00a6242506473373db769ef81f9a424ffba56328b73eac8af96d5163952955dac2f4a91f13ca1c27179378775f82956d544ae0cd1c12 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 167f0d09dc91f9e3106c37b65d8a06376eb087e132e5ab1e6a0274ee57dd8bcb4e89f0e008aacd917c7be7804d2fad8be089b00e3a31f0c117122a449be5b92c languageName: node linkType: hard -"@react-stately/data@npm:^3.11.6": - version: 3.11.6 - resolution: "@react-stately/data@npm:3.11.6" +"@react-stately/combobox@npm:^3.10.2": + version: 3.10.2 + resolution: "@react-stately/combobox@npm:3.10.2" dependencies: - "@react-types/shared": ^3.24.1 + "@react-stately/collections": ^3.12.1 + "@react-stately/form": ^3.1.1 + "@react-stately/list": ^3.11.2 + "@react-stately/overlays": ^3.6.13 + "@react-stately/select": ^3.6.10 + "@react-stately/utils": ^3.10.5 + "@react-types/combobox": ^3.13.2 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 88b2708fa5cf6fbd40c6bdb4574e2225781d4d26d4e1d08de89c2c83e1328efde5f8c69da1a7b5902d8cad9d1237e399da5c1cc081b676074d8d5e8fb2fd1fec + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 8657b5c096bc37271b16ee3e23bf2e09602a274a50b40e32412794c6825fa94847b4daa7293df0c2c0ebdfd983a4d4d83c4cbd76fc499aeef6952dc8ae29443d languageName: node linkType: hard -"@react-stately/datepicker@npm:^3.10.2": - version: 3.10.2 - resolution: "@react-stately/datepicker@npm:3.10.2" +"@react-stately/data@npm:^3.12.1": + version: 3.12.1 + resolution: "@react-stately/data@npm:3.12.1" dependencies: - "@internationalized/date": ^3.5.5 - "@internationalized/string": ^3.2.3 - "@react-stately/form": ^3.0.5 - "@react-stately/overlays": ^3.6.10 - "@react-stately/utils": ^3.10.3 - "@react-types/datepicker": ^3.8.2 - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 6ca8d83bca658924963e89923c97689d1c8b9fadacb8ef5150dc5fc417437b90de3e7aba13cd5c6209472dde34b6f80f343223230587cc0e8b7ac4c1a78d3682 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: ed80db0371fa5fd0da0fca817f39fdc243c157f9699fb35cd3b8731f3efe845d66d19ef013771b5faaaf885f711637d88365635b17bd0b082d0af6817d42b747 languageName: node linkType: hard -"@react-stately/dnd@npm:^3.4.2": - version: 3.4.2 - resolution: "@react-stately/dnd@npm:3.4.2" +"@react-stately/datepicker@npm:^3.12.0": + version: 3.12.0 + resolution: "@react-stately/datepicker@npm:3.12.0" dependencies: - "@react-stately/selection": ^3.16.2 - "@react-types/shared": ^3.24.1 + "@internationalized/date": ^3.7.0 + "@internationalized/string": ^3.2.5 + "@react-stately/form": ^3.1.1 + "@react-stately/overlays": ^3.6.13 + "@react-stately/utils": ^3.10.5 + "@react-types/datepicker": ^3.10.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 9a6ccdc05c1cf90e21a3eeb6c5e3fb4cdfe504973843d2b5981a03c9da3aeff61a42bb18ed78c83f5d54f756c55f8fec2cce4ac324db6039ff2072571741e828 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 45ca4b51a4be7c3ef9f6fa164c6c91e21306a6e6f5de2e7cde2584c1c22269e4484d694eda02176533156f1b313922792dbdfecdcaf8156c98f521fabcacf34a languageName: node linkType: hard -"@react-stately/flags@npm:^3.0.3": - version: 3.0.3 - resolution: "@react-stately/flags@npm:3.0.3" +"@react-stately/disclosure@npm:^3.0.1": + version: 3.0.1 + resolution: "@react-stately/disclosure@npm:3.0.1" dependencies: + "@react-stately/utils": ^3.10.5 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 - checksum: 8b88ccde3224efdafc947c9ee416fa45d0cf71f3d992790a6c0ba8227ca668e6d53e63fb3b2c2a3bcc80be92595c38b2473ba5b42bd81099ba24ebcf23635e8e + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: c9481a5b4e6f564e69c9d51d393588d83f1e7ba0ccfa434ef28a616c51ce381d29fb87d58d6d565412588c772b2947b17fa8b44fde6a5d367485ae7acfa93ab1 languageName: node linkType: hard -"@react-stately/form@npm:^3.0.5": +"@react-stately/dnd@npm:^3.5.1": + version: 3.5.1 + resolution: "@react-stately/dnd@npm:3.5.1" + dependencies: + "@react-stately/selection": ^3.19.0 + "@react-types/shared": ^3.27.0 + "@swc/helpers": ^0.5.0 + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 66a0c67c8e9a9c71cb24e8d370c17581775e9da3470fffcc6e80bf50450ed9fc800fc3d8627ea9407b46651b36326e139dd6d5fc251779b15b866072de0d461b + languageName: node + linkType: hard + +"@react-stately/flags@npm:^3.0.5": version: 3.0.5 - resolution: "@react-stately/form@npm:3.0.5" + resolution: "@react-stately/flags@npm:3.0.5" dependencies: - "@react-types/shared": ^3.24.1 + "@swc/helpers": ^0.5.0 + checksum: 8a2aaacd77bac14ea8e71726350bc30bd252fe5bcd70a72a26da5d433014788e1395ef0c3cb878492de9758e44243fb6470585e697874109c3924e1699a94fc7 + languageName: node + linkType: hard + +"@react-stately/form@npm:^3.1.1": + version: 3.1.1 + resolution: "@react-stately/form@npm:3.1.1" + dependencies: + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 7b78d8ec2e5f4c2957e3fb5a0b12295dd30213cfdea56783a55d01ba0a54815f54a43b98e84e9fdda1a1da10d8f28e25b823a58724846eb5b571d058fcf9d295 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: c79e087d0950e24c10d8f2acfc5c9d89f4a680bce22c7664bb397f6188158300a3d186d18a4d5650d0cca1da970fdbe8a81be910cdd7936d3795a0a42884953d languageName: node linkType: hard -"@react-stately/grid@npm:^3.9.2": - version: 3.9.2 - resolution: "@react-stately/grid@npm:3.9.2" +"@react-stately/grid@npm:^3.10.1": + version: 3.10.1 + resolution: "@react-stately/grid@npm:3.10.1" dependencies: - "@react-stately/collections": ^3.10.9 - "@react-stately/selection": ^3.16.2 - "@react-types/grid": ^3.2.8 - "@react-types/shared": ^3.24.1 + "@react-stately/collections": ^3.12.1 + "@react-stately/selection": ^3.19.0 + "@react-types/grid": ^3.2.11 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 2affc6b1afa6b480f84dc72b1dcda5e6d1eb22f44ef32b5576dc6a29e823d7317274ba7bc73bdbbc2aaf5962ea14537bb1ba987dd5a3e857d6630d4253136843 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 5c53c3db9a67fcdc777db04d2b163b313aa4d16cce611ca8be5c0968ef68db2a79f3102a3f2bc08b8a219baa7e51c440b02c09df37442d6f52f4c01330dbbc62 languageName: node linkType: hard -"@react-stately/layout@npm:^4.0.2": - version: 4.0.2 - resolution: "@react-stately/layout@npm:4.0.2" +"@react-stately/layout@npm:^4.1.1": + version: 4.1.1 + resolution: "@react-stately/layout@npm:4.1.1" dependencies: - "@react-stately/collections": ^3.10.9 - "@react-stately/table": ^3.12.2 - "@react-stately/virtualizer": ^4.0.2 - "@react-types/grid": ^3.2.8 - "@react-types/shared": ^3.24.1 - "@react-types/table": ^3.10.1 + "@react-stately/collections": ^3.12.1 + "@react-stately/table": ^3.13.1 + "@react-stately/virtualizer": ^4.2.1 + "@react-types/grid": ^3.2.11 + "@react-types/shared": ^3.27.0 + "@react-types/table": ^3.10.4 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 6dcbac045c17b74ed0318dd2cd9517626fe5ce3f7b781cab9cd60240ec3bf9d113146999481f71cd349584579b46504e4e5f7c61f1f0ca404392830a1cd704e5 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 2aca555a14fde2be790618c1be80af752900fc090ef17a50154bbc25b61e5750cc76438651ed63a30306ffabaddd869d79ee1b1577d0d54aedc46b191b079a11 languageName: node linkType: hard -"@react-stately/list@npm:^3.10.8": - version: 3.10.8 - resolution: "@react-stately/list@npm:3.10.8" +"@react-stately/list@npm:^3.10.8, @react-stately/list@npm:^3.11.2": + version: 3.11.2 + resolution: "@react-stately/list@npm:3.11.2" dependencies: - "@react-stately/collections": ^3.10.9 - "@react-stately/selection": ^3.16.2 - "@react-stately/utils": ^3.10.3 - "@react-types/shared": ^3.24.1 + "@react-stately/collections": ^3.12.1 + "@react-stately/selection": ^3.19.0 + "@react-stately/utils": ^3.10.5 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 16e8fd6fe178dfe58e7c4b828367cf95b11a2d6300ebc72e514fa0654886d0b67c04e413ccd679ffb5769951e8ba2cb27bf677f44ce73bfbd831c5e0dcd24cae + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 21b9279332face88510ed8f5b3c7f7a11b72b7f2360b3d8c37cde5035ccf13ca21afa0d6553f9384a52a2124267121362a8717c6d9b7b5e14e316d820379e107 languageName: node linkType: hard -"@react-stately/menu@npm:^3.8.2": - version: 3.8.2 - resolution: "@react-stately/menu@npm:3.8.2" +"@react-stately/menu@npm:^3.9.1": + version: 3.9.1 + resolution: "@react-stately/menu@npm:3.9.1" dependencies: - "@react-stately/overlays": ^3.6.10 - "@react-types/menu": ^3.9.11 - "@react-types/shared": ^3.24.1 + "@react-stately/overlays": ^3.6.13 + "@react-types/menu": ^3.9.14 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 6f7e20cc76b83df949604e605dd5841444f477c64ed51236e5b3d84ec13d209eeb99294ab21bedf7d3b274d17364b53bbd43950dc04a4c61f1b40bd1a31b3b57 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: b91888427f84aa0e2323cdb2840a3dc48bafbdd327f8dc77b063da4633bbd74e741f2c0cdef40b72d7163e02df12904293d49c1037989017db3a460211591049 languageName: node linkType: hard -"@react-stately/numberfield@npm:^3.9.6": - version: 3.9.6 - resolution: "@react-stately/numberfield@npm:3.9.6" +"@react-stately/numberfield@npm:^3.9.9": + version: 3.9.9 + resolution: "@react-stately/numberfield@npm:3.9.9" dependencies: - "@internationalized/number": ^3.5.3 - "@react-stately/form": ^3.0.5 - "@react-stately/utils": ^3.10.3 - "@react-types/numberfield": ^3.8.5 + "@internationalized/number": ^3.6.0 + "@react-stately/form": ^3.1.1 + "@react-stately/utils": ^3.10.5 + "@react-types/numberfield": ^3.8.8 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 3d9cb3ac006bcc2cc7ffd4daa341caa21114aeec10bb46c9008251cc50c6f5b23f66572851492794d3b94f070d7e10872b8ef0bebc1e7e295c6f18c17340b374 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: c64e91cc5db0c7ff564a570cd13165a3010e6d97565fab12ac39739b71f034fc3e750631f80a08ad85dcb53aad17ae156ce3cfdc3b54457735bcf5299e6f9062 languageName: node linkType: hard -"@react-stately/overlays@npm:^3.6.10": - version: 3.6.10 - resolution: "@react-stately/overlays@npm:3.6.10" +"@react-stately/overlays@npm:^3.6.13": + version: 3.6.13 + resolution: "@react-stately/overlays@npm:3.6.13" dependencies: - "@react-stately/utils": ^3.10.3 - "@react-types/overlays": ^3.8.9 + "@react-stately/utils": ^3.10.5 + "@react-types/overlays": ^3.8.12 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 45623d00eb6c1981b6d460255db0e4043b6d02191fb364b9c2fe83a4ec032efef04dfbd3e39636e10457674cdd709e7a59fb4a1f169e2ffdb20bfdb408ee603d + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: b1cd9f95b2fadf38fd27b543d91459234767bc3ff13ffa9ba7d6bc8d325e7f84aa572fadf6740dc44a1f36038fcbde8d28667098ff762bdcc9aef6f8f40cfe12 languageName: node linkType: hard -"@react-stately/radio@npm:^3.10.7, @react-stately/radio@npm:^3.6.2": - version: 3.10.7 - resolution: "@react-stately/radio@npm:3.10.7" +"@react-stately/radio@npm:^3.10.10, @react-stately/radio@npm:^3.6.2": + version: 3.10.10 + resolution: "@react-stately/radio@npm:3.10.10" dependencies: - "@react-stately/form": ^3.0.5 - "@react-stately/utils": ^3.10.3 - "@react-types/radio": ^3.8.3 - "@react-types/shared": ^3.24.1 + "@react-stately/form": ^3.1.1 + "@react-stately/utils": ^3.10.5 + "@react-types/radio": ^3.8.6 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 1754055a38b5b240082bdc58c3e142f1ed18f549fed6f083738ca543ef2502ec4f72527ace39f0063258c9b14c3b128d480b2288b80102afbad66d7f6772cc50 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 40c1b1a651f14c583170e1eae8e1dc9acd9a5599db47105e9ab84044b734a4e59d3925fe6355bd873f829cc2e8274c3854505389b67ee86af26305ead0e01bde languageName: node linkType: hard -"@react-stately/searchfield@npm:^3.5.6": - version: 3.5.6 - resolution: "@react-stately/searchfield@npm:3.5.6" +"@react-stately/searchfield@npm:^3.5.9": + version: 3.5.9 + resolution: "@react-stately/searchfield@npm:3.5.9" dependencies: - "@react-stately/utils": ^3.10.3 - "@react-types/searchfield": ^3.5.8 + "@react-stately/utils": ^3.10.5 + "@react-types/searchfield": ^3.5.11 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: c6804ca2108212dc61bd0daa38fe89c22071dfe611bb7eaf81a250c1e4fdff8e09f57b0d7ce5c9aebe8dc819ad389e4e112916c678b8332b9fc69012d0e6cc8e + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: d493758f89965e0f77408e45233971d4d061451d3a8862fcf16aab18d4787390c4041739a718f7cfe8a7749054d269982999eedf2931d15301eb128eca3123ff languageName: node linkType: hard -"@react-stately/select@npm:^3.6.7": - version: 3.6.7 - resolution: "@react-stately/select@npm:3.6.7" +"@react-stately/select@npm:^3.6.10": + version: 3.6.10 + resolution: "@react-stately/select@npm:3.6.10" dependencies: - "@react-stately/form": ^3.0.5 - "@react-stately/list": ^3.10.8 - "@react-stately/overlays": ^3.6.10 - "@react-types/select": ^3.9.6 - "@react-types/shared": ^3.24.1 + "@react-stately/form": ^3.1.1 + "@react-stately/list": ^3.11.2 + "@react-stately/overlays": ^3.6.13 + "@react-types/select": ^3.9.9 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: db4daef47d8f3092081d48d448de8604533a3fb68df5ed69442978fe71e6dc6a7bfa237a12ba71e1477209ffcd13335c45908a3a4ae4fe2d5c7c834f6a267583 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 5810f1450a1dc3f6c5831c14ea722d19e3999e0588295415b08617a380828f13f58299093efc0991b0a1084e48af4f65c48997033dbe7cde1810f42b257f88c0 languageName: node linkType: hard -"@react-stately/selection@npm:^3.16.2": - version: 3.16.2 - resolution: "@react-stately/selection@npm:3.16.2" +"@react-stately/selection@npm:^3.19.0": + version: 3.19.0 + resolution: "@react-stately/selection@npm:3.19.0" dependencies: - "@react-stately/collections": ^3.10.9 - "@react-stately/utils": ^3.10.3 - "@react-types/shared": ^3.24.1 + "@react-stately/collections": ^3.12.1 + "@react-stately/utils": ^3.10.5 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: aca17fdcc22b7dbb80508ea53f231f400f0caa14bca35e9e135a87d87f70fe161177563971e1d4d9867cfc7a91f909f5e54b3f652298a5a7031f7edae0441a33 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 57dc87cc1445b251e42f26e5e1f4bed354bebbda44507dedf3f65a5c97f4675dab55c6ab6d1cceabd455a3467d1e4597c2ccc8c9f153a5436a935b38619e9790 languageName: node linkType: hard -"@react-stately/slider@npm:^3.5.7, @react-stately/slider@npm:^3.6.1": +"@react-stately/slider@npm:^3.6.1": version: 3.6.1 resolution: "@react-stately/slider@npm:3.6.1" dependencies: @@ -7609,81 +7932,82 @@ __metadata: languageName: node linkType: hard -"@react-stately/table@npm:^3.12.2": - version: 3.12.2 - resolution: "@react-stately/table@npm:3.12.2" +"@react-stately/table@npm:^3.13.1": + version: 3.13.1 + resolution: "@react-stately/table@npm:3.13.1" dependencies: - "@react-stately/collections": ^3.10.9 - "@react-stately/flags": ^3.0.3 - "@react-stately/grid": ^3.9.2 - "@react-stately/selection": ^3.16.2 - "@react-stately/utils": ^3.10.3 - "@react-types/grid": ^3.2.8 - "@react-types/shared": ^3.24.1 - "@react-types/table": ^3.10.1 + "@react-stately/collections": ^3.12.1 + "@react-stately/flags": ^3.0.5 + "@react-stately/grid": ^3.10.1 + "@react-stately/selection": ^3.19.0 + "@react-stately/utils": ^3.10.5 + "@react-types/grid": ^3.2.11 + "@react-types/shared": ^3.27.0 + "@react-types/table": ^3.10.4 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 1395a83634e6a948ff2260f987d4fdadaf830a6602286d6965e764c15ad82bf2060aeeb9be1f6eee37ae2b5aa783dab4d82115c04803ad053575842030f914d5 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 489b2cee32eb6a14b31643c0eebdb5f20a9c341207865c3dab661043a818a03be4ecf2cbd06c0538d34915ddb30c906f0f5eb79bd8db6247aa10b253ba357f32 languageName: node linkType: hard -"@react-stately/tabs@npm:^3.6.9": - version: 3.6.9 - resolution: "@react-stately/tabs@npm:3.6.9" +"@react-stately/tabs@npm:^3.7.1": + version: 3.7.1 + resolution: "@react-stately/tabs@npm:3.7.1" dependencies: - "@react-stately/list": ^3.10.8 - "@react-types/shared": ^3.24.1 - "@react-types/tabs": ^3.3.9 + "@react-stately/list": ^3.11.2 + "@react-types/shared": ^3.27.0 + "@react-types/tabs": ^3.3.12 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: d5eed2cf80f8dbb89c1157615dfbbf31c69945a54849ee0f184bcce488b5b5da32e4df1e7be88821c1b96f2ff72097f06db9aa04de0a9ef90e8270a667393d9d + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 78687813e519e4d1a0efdc1b5a4a465f2b6693ac6940d76ed4ff19d737c9dfe434f78553dd8f2fe169bf944fe793e2f343c888540b5a3c6a4867bc1acdd72891 languageName: node linkType: hard -"@react-stately/toggle@npm:^3.4.4, @react-stately/toggle@npm:^3.7.7": - version: 3.7.7 - resolution: "@react-stately/toggle@npm:3.7.7" +"@react-stately/toggle@npm:^3.4.4, @react-stately/toggle@npm:^3.8.1": + version: 3.8.1 + resolution: "@react-stately/toggle@npm:3.8.1" dependencies: - "@react-stately/utils": ^3.10.3 - "@react-types/checkbox": ^3.8.3 + "@react-stately/utils": ^3.10.5 + "@react-types/checkbox": ^3.9.1 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 1e424c4ba32a92e8d0bb2db7c03e388ab491f13d24e70c6abd4988f31d63fb86eecc5267adbfae73b30ed8912db99a24977821661cbc18b82b36152c5174e13f + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: e97f1955bb30ec28d085ffbce0f143cd631742e45784620afc8255b1761deef754ca77a90fcaa7b483807fddc020400b63961e6ac67a8d7ccee3f5447c8ca2b6 languageName: node linkType: hard -"@react-stately/tooltip@npm:^3.4.12": - version: 3.4.12 - resolution: "@react-stately/tooltip@npm:3.4.12" +"@react-stately/tooltip@npm:^3.5.1": + version: 3.5.1 + resolution: "@react-stately/tooltip@npm:3.5.1" dependencies: - "@react-stately/overlays": ^3.6.10 - "@react-types/tooltip": ^3.4.11 + "@react-stately/overlays": ^3.6.13 + "@react-types/tooltip": ^3.4.14 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 2a20ceec33f0c2240f906a284a51670b1c0bdd941bcf028b1a5c307f96d1818c322541dca10c17fd3c0bd334e03ff418a5a3918e714567e9e29ee76fc74be0b3 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 3848c1019d90b4bf9ec27eea704622e532ccf56687b316562e5072e641f8a0a7364ca685b739a74b1e737b3aebaab1d762de6bcf7669f8ce175f7101bc6fa699 languageName: node linkType: hard -"@react-stately/tree@npm:^3.8.4": - version: 3.8.4 - resolution: "@react-stately/tree@npm:3.8.4" +"@react-stately/tree@npm:^3.8.7": + version: 3.8.7 + resolution: "@react-stately/tree@npm:3.8.7" dependencies: - "@react-stately/collections": ^3.10.9 - "@react-stately/selection": ^3.16.2 - "@react-stately/utils": ^3.10.3 - "@react-types/shared": ^3.24.1 + "@react-stately/collections": ^3.12.1 + "@react-stately/selection": ^3.19.0 + "@react-stately/utils": ^3.10.5 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 807e58324ffe4ef02412af50c79f11ec530a95616ad6235f548ce118a879a9e674c464edfd81e035999f4cb6052d2bedaeda1d9df43c0073ad5240d11cf677d9 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: d08af87df5d4f97c6565164693ef417f70c713a460431eea6fbac7c237950a3d68f50022e0795d52e64930e76f6ecf0174c6dbfc088c8575f2246964ff741eb4 languageName: node linkType: hard -"@react-stately/utils@npm:^3.10.3, @react-stately/utils@npm:^3.10.5": +"@react-stately/utils@npm:^3.10.3, @react-stately/utils@npm:^3.10.4, @react-stately/utils@npm:^3.10.5": version: 3.10.5 resolution: "@react-stately/utils@npm:3.10.5" dependencies: @@ -7694,16 +8018,17 @@ __metadata: languageName: node linkType: hard -"@react-stately/virtualizer@npm:^4.0.2": - version: 4.0.2 - resolution: "@react-stately/virtualizer@npm:4.0.2" +"@react-stately/virtualizer@npm:^4.2.1": + version: 4.2.1 + resolution: "@react-stately/virtualizer@npm:4.2.1" dependencies: - "@react-aria/utils": ^3.25.2 - "@react-types/shared": ^3.24.1 + "@react-aria/utils": ^3.27.0 + "@react-types/shared": ^3.27.0 "@swc/helpers": ^0.5.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: cb516e0fa4e6bb43ab929c84d36ab12d2a2ec7141f296108117f4c4449a59eb09392c3def0d36248acc7a9a59886c999335b5c5e7383e52eb47cfb453acb6612 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 8f2223edccdcac1e2fa53b942201532244ceb9d94f4f262fe1b6e3f081457d6c00999998776a3d3db279311282cd8db4393d5582d6a5be9d38bc484599efe142 languageName: node linkType: hard @@ -7718,120 +8043,133 @@ __metadata: languageName: node linkType: hard -"@react-types/breadcrumbs@npm:^3.7.7": - version: 3.7.7 - resolution: "@react-types/breadcrumbs@npm:3.7.7" +"@react-types/autocomplete@npm:3.0.0-alpha.28": + version: 3.0.0-alpha.28 + resolution: "@react-types/autocomplete@npm:3.0.0-alpha.28" dependencies: - "@react-types/link": ^3.5.7 - "@react-types/shared": ^3.24.1 + "@react-types/combobox": ^3.13.2 + "@react-types/searchfield": ^3.5.11 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 56e25e5e027d794b039887e535ba74cf9f1dfc7b90f9348841fa1c0d562c26e9dfe9043dde8ae9ef664cf83ab23e4713bda800011a78602b70e8e4e2d73c005f + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 6bcbd310dd28fe695d49aa91c643cf3b43051c5af57d266a06ba3936a6158ba5fb92bbecc6bd4f511ea7f43086f91cefa9a94414f59f617b259ce1787010fed6 languageName: node linkType: hard -"@react-types/button@npm:^3.9.6": - version: 3.9.6 - resolution: "@react-types/button@npm:3.9.6" +"@react-types/breadcrumbs@npm:^3.7.10": + version: 3.7.10 + resolution: "@react-types/breadcrumbs@npm:3.7.10" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/link": ^3.5.10 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: e4454a005998101a23ddf84d076646c79f679383f8a81bfd3285ff0906182f0f67f11434283d3568e846ddfb9c86972f5e79aab8f0fc9c86de243185d39b5283 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 8f55c65da64a8563627c8b4b7898c19fe75a023737dd976965dcfd6d6652ffc9f6bdfd3ddd350bf7719463f1cad1d62ec461d5802794b652edcd1ed05057c2f2 languageName: node linkType: hard -"@react-types/calendar@npm:^3.4.9": - version: 3.4.9 - resolution: "@react-types/calendar@npm:3.4.9" +"@react-types/button@npm:^3.10.2": + version: 3.10.2 + resolution: "@react-types/button@npm:3.10.2" dependencies: - "@internationalized/date": ^3.5.5 - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 8b806a8d86dd321286eebd9932a2caff682c35a451438221b6325112f22668da9e551803c86c87b8ae17deba126326acb6c115b9449ebd6dbccf072ec441a6d2 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 7d5157c33a495a6b218b1b8c6cc11e406a5ecf028293c0d6f3303744af60802f9dfa2eff669741b38368406f2791df1d907f18c8d91cf903dd65b1e17f606cee languageName: node linkType: hard -"@react-types/checkbox@npm:^3.8.3": - version: 3.8.3 - resolution: "@react-types/checkbox@npm:3.8.3" +"@react-types/calendar@npm:^3.6.0": + version: 3.6.0 + resolution: "@react-types/calendar@npm:3.6.0" dependencies: - "@react-types/shared": ^3.24.1 + "@internationalized/date": ^3.7.0 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: ac46f7fb37ea0b5942e5032c5317923fdcbe68ce853c1e2846d37a87a8b4ae4fba8934d1a3300b8f49f9c8ab470f42608e3fb9e965d9251e3b676acc01605936 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: d7d52f370e4a6e695283bcbb4d6cc8399d25c12393b7aea2140af837bef8ed0b72da0f8afce322be43bd4d1b5103b2e8a7ecdd1d2d5cf648c8d35138d6cfc9f7 languageName: node linkType: hard -"@react-types/color@npm:3.0.0-rc.1": - version: 3.0.0-rc.1 - resolution: "@react-types/color@npm:3.0.0-rc.1" +"@react-types/checkbox@npm:^3.9.1": + version: 3.9.1 + resolution: "@react-types/checkbox@npm:3.9.1" dependencies: - "@react-types/shared": ^3.24.1 - "@react-types/slider": ^3.7.5 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 7671ef2db41a11da64338df6d8f7c0f81bd2e7883180689718a828e35522cfd982e0c5ad7ee3f38905cec6df0a6b59e80b232cce253c90450358def0a208f33c + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 29c5277c134a808cb601a65b1f2a0553be345bb0680b5c632ac6bbb0864056dca55e1260dd089527133cf0488df0c140d6c64e9456d50921de3c3cd712d00dc8 languageName: node linkType: hard -"@react-types/combobox@npm:^3.12.1": - version: 3.12.1 - resolution: "@react-types/combobox@npm:3.12.1" +"@react-types/color@npm:^3.0.2": + version: 3.0.2 + resolution: "@react-types/color@npm:3.0.2" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 + "@react-types/slider": ^3.7.8 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: f214b7dd84d08355cde04f6071ec682522221ab01fee9ccda39ffcac81061b51e465508d9f85ace7e17eab14772870e1637b18b67cfd27598f8ff48481c2f86a + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 68c266f7291b5f26527e7bdeaa0abdfa84f5ed0afc7a1abd33aea051e32dc5aaefb4eb9359c52ad271cf079f8bb899839e67f36a46d774b4d3b1b26802f8f02d languageName: node linkType: hard -"@react-types/datepicker@npm:^3.8.2": - version: 3.8.2 - resolution: "@react-types/datepicker@npm:3.8.2" +"@react-types/combobox@npm:^3.13.2": + version: 3.13.2 + resolution: "@react-types/combobox@npm:3.13.2" dependencies: - "@internationalized/date": ^3.5.5 - "@react-types/calendar": ^3.4.9 - "@react-types/overlays": ^3.8.9 - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 18e370332e22678a1d32b670ecddf9b3dcc3bdcb32dfc9a2a6f74ed91e1930b48717a47102615b35f49c8d74a346ae5ca09291ad3238a44b0944a2408b65b444 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 80acf347ce204785f466a8ea19e0aea1e927f9f339f6fa83163c2cb908d1d12d9af84a886c7420062ad26d10f5fb0bd9e5da256fd437686f2b7f831b9449aa42 languageName: node linkType: hard -"@react-types/dialog@npm:^3.5.12": - version: 3.5.12 - resolution: "@react-types/dialog@npm:3.5.12" +"@react-types/datepicker@npm:^3.10.0": + version: 3.10.0 + resolution: "@react-types/datepicker@npm:3.10.0" dependencies: - "@react-types/overlays": ^3.8.9 - "@react-types/shared": ^3.24.1 + "@internationalized/date": ^3.7.0 + "@react-types/calendar": ^3.6.0 + "@react-types/overlays": ^3.8.12 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: acdcd016dd239bc72d60f75c56245158023a5eb02b1e635d97c78c65463b8aeb9a0d9aca255b62c0b9ade4086bad403cf80947bca2a6455ac401c03c7c85813e + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: ca53e6a25392a6dee69041ae8136524beac7f0c52f2547c2c783bc49864de649c0018e05620a6056c1602292bb53150060445c24aaa242040c1f136780a2f0e4 languageName: node linkType: hard -"@react-types/form@npm:^3.7.6": - version: 3.7.6 - resolution: "@react-types/form@npm:3.7.6" +"@react-types/dialog@npm:^3.5.15": + version: 3.5.15 + resolution: "@react-types/dialog@npm:3.5.15" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/overlays": ^3.8.12 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 53360897a0cb7b26eb6c2089ea3a26702979eda6d2e002c6edb8e1ca396711eb6e5480c2946591942e0fa89ce1b004b556ef45fc5e438ce3b8e78913ba94ba50 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 38bc4c40ab576233ec48adc3d5070e9e474fb7b820cee9f9e95cd1b6ed82039d0c4a216200768a9d89493839bcd798d0e0e2352969287b75c6509b04f39e8d59 languageName: node linkType: hard -"@react-types/grid@npm:^3.2.8": - version: 3.2.8 - resolution: "@react-types/grid@npm:3.2.8" +"@react-types/form@npm:^3.7.9": + version: 3.7.9 + resolution: "@react-types/form@npm:3.7.9" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 4e2da3c8e48775728f13e11ddb715ed684f8bdf6cbc06bb43c3bc6304c276326edf65b534f9383c0159db93b5680e8a5a88562cdbdf671d7c6e094669397a615 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 6628e797a9644a31bb6afbb35aefdbf6cff99cb4b90832855552efbaf7e73e812035862002812087f45174859c09b5fc6f681b995a3cf2aa1d98483caffa0494 + languageName: node + linkType: hard + +"@react-types/grid@npm:^3.2.11": + version: 3.2.11 + resolution: "@react-types/grid@npm:3.2.11" + dependencies: + "@react-types/shared": ^3.27.0 + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 5bfc20737f618dd5bce9d6f0e6f07c1f7104d790127c8c4b680dd5b563262c72f3f9fad48224baa120324e965f7331ae65b844a59277a74d791a60579e3e169a languageName: node linkType: hard @@ -7846,115 +8184,115 @@ __metadata: languageName: node linkType: hard -"@react-types/link@npm:^3.5.7": - version: 3.5.7 - resolution: "@react-types/link@npm:3.5.7" +"@react-types/link@npm:^3.5.10": + version: 3.5.10 + resolution: "@react-types/link@npm:3.5.10" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: c554c0c015f1d20e6a2c5cc49af65fc9daff852ce76af6f56e68199909ec9052c72cbe15c8f10d6f62485cffdfdaf7d81b0a5aeaa20828b0ab9fd0046895de65 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 28adb848382002b57eb9a3a89b73117e68d204521425aa5e110fc39a5bad2c1c5b8a5eadd5306593ffa24474a69fb773cf00d40620014b58655af0b93a4da1e4 languageName: node linkType: hard -"@react-types/listbox@npm:^3.5.1": - version: 3.5.1 - resolution: "@react-types/listbox@npm:3.5.1" +"@react-types/listbox@npm:^3.5.4": + version: 3.5.4 + resolution: "@react-types/listbox@npm:3.5.4" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: b0732ce82be601b7f29c3c42994f9009cf23e8564e5a40439735940c549a1fa75950c38acc4434dc94cf8aed688d50dd47148d6487882095d3559f4bb5f5a1d4 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 0ead86a70d2628b83c3c88867746d38294485127e238ec219ce3af7a9055635bf01243dea81ea041713900a6aceab6f1a2711b82993b0f4df2d8e418ec2e40ca languageName: node linkType: hard -"@react-types/menu@npm:^3.9.11": - version: 3.9.11 - resolution: "@react-types/menu@npm:3.9.11" +"@react-types/menu@npm:^3.9.14": + version: 3.9.14 + resolution: "@react-types/menu@npm:3.9.14" dependencies: - "@react-types/overlays": ^3.8.9 - "@react-types/shared": ^3.24.1 + "@react-types/overlays": ^3.8.12 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 61b27f5520183689dda94d06c9ee7cbd0e1e7b3c0c91df1f1e3cfb9f62fbd370ab2998255c19bb9cf7145a07ee1fc8324bc26e14d645214001b1bd0d8b28c780 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 2e0396acc3ed7cced9699186aa32640e8842521dbb71db0b068c409add96c7c6b0c3e765008f191a31f78bab2480b16e58df194d61c79b125a58359c803702ed languageName: node linkType: hard -"@react-types/meter@npm:^3.4.3": - version: 3.4.3 - resolution: "@react-types/meter@npm:3.4.3" +"@react-types/meter@npm:^3.4.6": + version: 3.4.6 + resolution: "@react-types/meter@npm:3.4.6" dependencies: - "@react-types/progress": ^3.5.6 + "@react-types/progress": ^3.5.9 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 04787d37709dd09f3dca711def215b86d91f5e79475c08999169cf36d51d751b877939636885738414ea169ee39116fd21a84011dd7bfb4e1597d896c0aa4652 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 09f63a109204bbf6b3ee171b5c7573e21df3f8b590ab3a4d366eae669b7f38271a7c90842c95107c26b73412d715e5079efa8ccfabe521448da367925a96b623 languageName: node linkType: hard -"@react-types/numberfield@npm:^3.8.5": - version: 3.8.5 - resolution: "@react-types/numberfield@npm:3.8.5" +"@react-types/numberfield@npm:^3.8.8": + version: 3.8.8 + resolution: "@react-types/numberfield@npm:3.8.8" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 9f67d4305b8a127ef20f7a47b90283a01eea68beec2077c0bf9f667843667372de5be751825616d7a16f4bfcc9f1ba64d47d577dd217baa4c26dfb9918fd789b + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: ebe57f81b158451b18e807d2c9112b68453f0505bfca7fe1f9f67119a42f726c12d07b1c7fbd2df8e3e2c4943ea1ed0be3311e5f42cc57925d8f8d5e85965338 languageName: node linkType: hard -"@react-types/overlays@npm:^3.8.9": - version: 3.8.9 - resolution: "@react-types/overlays@npm:3.8.9" +"@react-types/overlays@npm:^3.8.12": + version: 3.8.12 + resolution: "@react-types/overlays@npm:3.8.12" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: e535ff53ce8835f57e2d117c0a898b1a9b876ef25abc4d3617f1a3203b102c2cc5371d73a6bcdcb65bf3a35e767e55f7930b8c9225c422686923f1e0d31bbe52 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 8bfed3dbc884d0b0bc88e6085e83632cfc4433488ba153eb2a68bee5fd485b4891be5763734cdc5daeca744ac84813ee5050224f3b82b98a439e0984163f8d0a languageName: node linkType: hard -"@react-types/progress@npm:^3.5.6": - version: 3.5.6 - resolution: "@react-types/progress@npm:3.5.6" +"@react-types/progress@npm:^3.5.9": + version: 3.5.9 + resolution: "@react-types/progress@npm:3.5.9" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: cb1e1e21a1088f30d628ee2bca048905bfbd678a2007ea151ff83afb482c3d26d8f586078cbde7824005d1034331479e48919e93b029ce6101a167e830fa4701 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 0babbdc593eb3523bf7c4e2707cdbd765fa527cab28f6d8e72c0ae3ccd562c6c82c5063775bde9af29f3d84f58d429874dfb5781f18543550fb79bad929b3949 languageName: node linkType: hard -"@react-types/radio@npm:^3.8.3": - version: 3.8.3 - resolution: "@react-types/radio@npm:3.8.3" +"@react-types/radio@npm:^3.8.6": + version: 3.8.6 + resolution: "@react-types/radio@npm:3.8.6" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 0f09a8fd5ea1875aa996842b5ec944a95407b6b023fc2d247c1db94acf2ffdf0be3895c2ad6cae216551a3623b11a66b3443abffe6861ac8d5d8dbd6075ebc14 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: a1a33bb2dbae7d3721902eb9b1c4c4358e028a361e1947a11aaad6cd6fadad21c443abf2cff1063b8f4fb6e06a5de0d940293ff6a73fb7e58ba03708aecbfed5 languageName: node linkType: hard -"@react-types/searchfield@npm:^3.5.8": - version: 3.5.8 - resolution: "@react-types/searchfield@npm:3.5.8" +"@react-types/searchfield@npm:^3.5.11": + version: 3.5.11 + resolution: "@react-types/searchfield@npm:3.5.11" dependencies: - "@react-types/shared": ^3.24.1 - "@react-types/textfield": ^3.9.6 + "@react-types/shared": ^3.27.0 + "@react-types/textfield": ^3.11.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 946e918eb662cd9226a1f424af14240b351e327f440950316b2d27f9a7741c4466c632b2d0cc963833a5fd324cba7044e30776ef460e4cbb0b99e2f524bd262a + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: adcf3ce29580898fb875bb2ddd86a6ea1a7cd50a1fca6e7f4ce351a37380f9e51f7988d40373574d207917d6463d95a2930c96529b3b6f41dabd818ad22c5828 languageName: node linkType: hard -"@react-types/select@npm:^3.9.6": - version: 3.9.6 - resolution: "@react-types/select@npm:3.9.6" +"@react-types/select@npm:^3.9.9": + version: 3.9.9 + resolution: "@react-types/select@npm:3.9.9" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 491fd1d3dac9514a4f5f67e6a194ec022c64082f4293090e8323cd1c74be3d26b8e0616117ab4484ac881e8923b1445a4e3389de7da487d0f48ebc09dc49ff6b + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: fd1c176aed901dd6c8272f72836aa288261180ec963a0699ddc8d292e442e2b5cd14a07eff9c285e694a8c9b550fc9a4402e6b9c80e4e748a5e09808eabb6754 languageName: node linkType: hard @@ -7967,7 +8305,7 @@ __metadata: languageName: node linkType: hard -"@react-types/slider@npm:^3.7.5, @react-types/slider@npm:^3.7.8": +"@react-types/slider@npm:^3.7.8": version: 3.7.8 resolution: "@react-types/slider@npm:3.7.8" dependencies: @@ -7978,60 +8316,60 @@ __metadata: languageName: node linkType: hard -"@react-types/switch@npm:^3.5.5": - version: 3.5.5 - resolution: "@react-types/switch@npm:3.5.5" +"@react-types/switch@npm:^3.5.8": + version: 3.5.8 + resolution: "@react-types/switch@npm:3.5.8" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 989aa9d113c5fa84a7999ca59ef56c0678197c1614a1ab9809070b4e482e06d8f42165508891876a88366f966b50b6cd9ddc66656ace26cc2c7552df517ba174 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: f747277f8912846f409c59774749a2c2a3ee9d0254b6b1c61b5442904c208d4204f9627674b042609e526da9a4ccae584e43499486785aa0431793d6247217f1 languageName: node linkType: hard -"@react-types/table@npm:^3.10.1": - version: 3.10.1 - resolution: "@react-types/table@npm:3.10.1" +"@react-types/table@npm:^3.10.4": + version: 3.10.4 + resolution: "@react-types/table@npm:3.10.4" dependencies: - "@react-types/grid": ^3.2.8 - "@react-types/shared": ^3.24.1 + "@react-types/grid": ^3.2.11 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: fe22e3cc6335c2a34c797eababbba9a5f43ce05bc3d92944cd78f5c5a4ef20cfb6d493c5e3e9ebd4f1b97ea405e6c33077ec76db065f0d63c4caae0ce51d99ae + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 0076a7ccf181e4dbf9561b01fb92f211963bae01e027653dfa55330e927d075b8111683cd88196e69690a41101534ce3af02067e3e172830e9f945a1005dd3c9 languageName: node linkType: hard -"@react-types/tabs@npm:^3.3.9": - version: 3.3.9 - resolution: "@react-types/tabs@npm:3.3.9" +"@react-types/tabs@npm:^3.3.12": + version: 3.3.12 + resolution: "@react-types/tabs@npm:3.3.12" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: d55286dc003e6c150af500f9b9821c0b547f9c85ed127197789ab7e61dff720f9d2bd42bfa1fbfff7baf125662093edc366bbcd1a2a849facdf3a56fc3783a80 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: d5e1d6b287da9c13435c5e4a667ff94fd5415dc23e79579d62e319fb7d416ae60ffc0635142e295d63c3831d436d4ce0fb848c6f762735488cbdf116d3df317f languageName: node linkType: hard -"@react-types/textfield@npm:^3.9.6": - version: 3.9.6 - resolution: "@react-types/textfield@npm:3.9.6" +"@react-types/textfield@npm:^3.11.0, @react-types/textfield@npm:^3.9.6": + version: 3.11.0 + resolution: "@react-types/textfield@npm:3.11.0" dependencies: - "@react-types/shared": ^3.24.1 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 80625f20ed30a6d154fd54cbecf88fdb26ec835b6f84db8581053fb48a323c7c77ce20c5c2006dfee0fadc8272e5100b66f59474cff6fd949ceb8b962ec2728f + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 6186701cf03395ad5fa6fb43bba255d52973f1736902e4f7e1abfb51b357044f554258b8fa3ba1f4a54da621c7fd3ca6a2688600d230f8364cb1139bb5af8ff0 languageName: node linkType: hard -"@react-types/tooltip@npm:^3.4.11": - version: 3.4.11 - resolution: "@react-types/tooltip@npm:3.4.11" +"@react-types/tooltip@npm:^3.4.14": + version: 3.4.14 + resolution: "@react-types/tooltip@npm:3.4.14" dependencies: - "@react-types/overlays": ^3.8.9 - "@react-types/shared": ^3.24.1 + "@react-types/overlays": ^3.8.12 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: d6eefbd4892d09db3d92b4e81ff539c029e323fd9b082f3b29e9d1d31cfed109d9d67cb687631a2e523676901f431048d94bdf96ccc8bcf58e9385020bffdf2d + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: a277fb24862beba0a008eab46635238e5c96d48081d2c39b1660bd8236181dc88a6522336f7a62b82901747a1103c1dd31b6c86c0b124040eec3c9c53a886b1c languageName: node linkType: hard @@ -8391,6 +8729,20 @@ __metadata: languageName: node linkType: hard +"@sapphire/async-queue@npm:^1.5.3": + version: 1.5.5 + resolution: "@sapphire/async-queue@npm:1.5.5" + checksum: 87218b46599728ce83f3829d246f939e6f5857aa002b55ac9c416864b9af16d242e09d069eaf96547596c5e7b042705038cbc9c5eebb07d490ba17271a688e67 + languageName: node + linkType: hard + +"@sapphire/snowflake@npm:^3.5.3": + version: 3.5.5 + resolution: "@sapphire/snowflake@npm:3.5.5" + checksum: 8f18a99fa2a9bcd7369851dd12abb337e4beaadeb294de50d638466690fe8d037a6e82628021ad5a971c75b6543501b20c72a859f9686ccabd0fd229fe45daed + languageName: node + linkType: hard + "@scarf/scarf@npm:^1.0.5": version: 1.1.0 resolution: "@scarf/scarf@npm:1.1.0" @@ -8474,6 +8826,16 @@ __metadata: languageName: node linkType: hard +"@selderee/plugin-htmlparser2@npm:^0.11.0": + version: 0.11.0 + resolution: "@selderee/plugin-htmlparser2@npm:0.11.0" + dependencies: + domhandler: ^5.0.3 + selderee: ^0.11.0 + checksum: 6deafedd153e492359f8f0407d20903d82f2ef4950e420f4b2ee6ffbb955753524631aac7d6a5fe61dc7c7893e6928b4d8409e886157ad64a60ab37bc08b17c4 + languageName: node + linkType: hard + "@sentry/browser@npm:6.2.4": version: 6.2.4 resolution: "@sentry/browser@npm:6.2.4" @@ -10854,10 +11216,10 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.105, @types/lodash@npm:^4.14.120, @types/lodash@npm:^4.14.167": - version: 4.14.191 - resolution: "@types/lodash@npm:4.14.191" - checksum: ba0d5434e10690869f32d5ea49095250157cae502f10d57de0a723fd72229ce6c6a4979576f0f13e0aa9fbe3ce2457bfb9fa7d4ec3d6daba56730a51906d1491 +"@types/lodash@npm:^4.14.105, @types/lodash@npm:^4.14.120, @types/lodash@npm:^4.14.167, @types/lodash@npm:^4.17.7": + version: 4.17.15 + resolution: "@types/lodash@npm:4.17.15" + checksum: 5037564154411f4ac0b187b914031c150520a7ca037dea007f774b7123c97c0da55b2e41ae81dc1bc80ff09e8d6a236455ea676d5062af12c592b8e81baec7bf languageName: node linkType: hard @@ -10923,13 +11285,13 @@ __metadata: languageName: node linkType: hard -"@types/node-fetch@npm:^2.6.11, @types/node-fetch@npm:^2.6.4": - version: 2.6.11 - resolution: "@types/node-fetch@npm:2.6.11" +"@types/node-fetch@npm:^2.5.10, @types/node-fetch@npm:^2.6.11, @types/node-fetch@npm:^2.6.4": + version: 2.6.12 + resolution: "@types/node-fetch@npm:2.6.12" dependencies: "@types/node": "*" form-data: ^4.0.0 - checksum: 180e4d44c432839bdf8a25251ef8c47d51e37355ddd78c64695225de8bc5dc2b50b7bb855956d471c026bb84bd7295688a0960085e7158cbbba803053492568b + checksum: 9647e68f9a125a090220c38d77b3c8e669c488658ae7506f1b4f9568214beba087624b1705bba1dc76649a65281ce3fd5b400e15266cbef8088027fb88777557 languageName: node linkType: hard @@ -10942,12 +11304,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=13.7.0": - version: 20.8.10 - resolution: "@types/node@npm:20.8.10" +"@types/node@npm:*, @types/node@npm:>=13.7.0, @types/node@npm:^22.9.0": + version: 22.13.4 + resolution: "@types/node@npm:22.13.4" dependencies: - undici-types: ~5.26.4 - checksum: 7c61190e43e8074a1b571e52ff14c880bc67a0447f2fe5ed0e1a023eb8a23d5f815658edb98890f7578afe0f090433c4a635c7c87311762544e20dd78723e515 + undici-types: ~6.20.0 + checksum: 39ecbd84fc2c6268c57f0479bc095cd304d2e97fee0b4ed7e6a77508aaadb28dc21be0ec91bf866ab2be822bf6c9749945795dbd6ba60e0851b50a967fd784b5 languageName: node linkType: hard @@ -11192,12 +11554,22 @@ __metadata: languageName: node linkType: hard -"@types/react-window@npm:^1.8.2": - version: 1.8.2 - resolution: "@types/react-window@npm:1.8.2" +"@types/react-window-infinite-loader@npm:^1.0.9": + version: 1.0.9 + resolution: "@types/react-window-infinite-loader@npm:1.0.9" dependencies: "@types/react": "*" - checksum: c127ed420d881510fe647539342e7c494802aab12fd6cb61f9f8ba47ef16d3683e632b7a6a07eb0d284ea8f0953ae7941eafa2c51c0bcb3b176d009eac09c79a + "@types/react-window": "*" + checksum: 9f2c27f24bfa726ceaef6612a4adbda745f3455c877193f68dfa48591274c670a6df4fa6870785cff5f948e289ceb9a247fb7cbf67e3cd555ab16d11866fd63f + languageName: node + linkType: hard + +"@types/react-window@npm:*, @types/react-window@npm:^1.8.2": + version: 1.8.8 + resolution: "@types/react-window@npm:1.8.8" + dependencies: + "@types/react": "*" + checksum: 253c9d6e0c942f34633edbddcbc369324403c42458ff004457c5bd5972961d8433a909c0cc1a89c918063d5eb85ecbdd774142af2555fae61f4ceb3ba9884b5a languageName: node linkType: hard @@ -11480,6 +11852,15 @@ __metadata: languageName: node linkType: hard +"@types/whatwg-url@npm:^11.0.2": + version: 11.0.5 + resolution: "@types/whatwg-url@npm:11.0.5" + dependencies: + "@types/webidl-conversions": "*" + checksum: 23a0c45aff51817807b473a6adb181d6e3bb0d27dde54e84883d5d5bc93358e95204d2188e7ff7fdc2cdaf157e97e1188ef0a22ec79228da300fc30d4a05b56a + languageName: node + linkType: hard + "@types/whatwg-url@npm:^8.2.1": version: 8.2.2 resolution: "@types/whatwg-url@npm:8.2.2" @@ -12190,6 +12571,13 @@ __metadata: languageName: node linkType: hard +"@vladfrangu/async_event_emitter@npm:^2.4.6": + version: 2.4.6 + resolution: "@vladfrangu/async_event_emitter@npm:2.4.6" + checksum: 924e35d9adf8a045c9846c0c96618aa61c40c776b52b8d6ee510781367004ec5fda8949bf5f0d54d1896b041fccc0e5a71844c379c87b955b6412f5f18615cd9 + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.11.1": version: 1.11.1 resolution: "@webassemblyjs/ast@npm:1.11.1" @@ -12352,6 +12740,13 @@ __metadata: languageName: node linkType: hard +"@xmldom/xmldom@npm:^0.8.6": + version: 0.8.10 + resolution: "@xmldom/xmldom@npm:0.8.10" + checksum: 4c136aec31fb3b49aaa53b6fcbfe524d02a1dc0d8e17ee35bd3bf35e9ce1344560481cd1efd086ad1a4821541482528672306d5e37cdbd187f33d7fadd3e2cf0 + languageName: node + linkType: hard + "@xstate/fsm@npm:^1.4.0": version: 1.6.5 resolution: "@xstate/fsm@npm:1.6.5" @@ -12472,7 +12867,7 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^1.0.0": +"abbrev@npm:1, abbrev@npm:^1.0.0": version: 1.1.1 resolution: "abbrev@npm:1.1.1" checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17 @@ -12645,6 +13040,13 @@ __metadata: languageName: node linkType: hard +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.3 + resolution: "agent-base@npm:7.1.3" + checksum: 87bb7ee54f5ecf0ccbfcba0b07473885c43ecd76cb29a8db17d6137a19d9f9cd443a2a7c5fd8a3f24d58ad8145f9eb49116344a66b107e1aeab82cf2383f4753 + languageName: node + linkType: hard + "agentkeepalive@npm:^4.2.1": version: 4.2.1 resolution: "agentkeepalive@npm:4.2.1" @@ -12712,15 +13114,15 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0, ajv@npm:^8.6.0, ajv@npm:^8.8.0": - version: 8.11.0 - resolution: "ajv@npm:8.11.0" +"ajv@npm:^8.0.0, ajv@npm:^8.17.1, ajv@npm:^8.6.0, ajv@npm:^8.8.0": + version: 8.17.1 + resolution: "ajv@npm:8.17.1" dependencies: - fast-deep-equal: ^3.1.1 + fast-deep-equal: ^3.1.3 + fast-uri: ^3.0.1 json-schema-traverse: ^1.0.0 require-from-string: ^2.0.2 - uri-js: ^4.2.2 - checksum: 5e0ff226806763be73e93dd7805b634f6f5921e3e90ca04acdf8db81eed9d8d3f0d4c5f1213047f45ebbf8047ffe0c840fa1ef2ec42c3a644899f69aa72b5bef + checksum: 1797bf242cfffbaf3b870d13565bd1716b73f214bb7ada9a497063aada210200da36e3ed40237285f3255acc4feeae91b1fb183625331bad27da95973f7253d9 languageName: node linkType: hard @@ -12880,6 +13282,7 @@ __metadata: version: 0.0.0-use.local resolution: "appsmith-rts@workspace:packages/rts" dependencies: + "@llamaindex/readers": 2.0.0 "@opentelemetry/exporter-trace-otlp-http": ^0.54.2 "@opentelemetry/instrumentation": ^0.54.2 "@opentelemetry/instrumentation-http": ^0.54.2 @@ -12898,6 +13301,7 @@ __metadata: express-validator: ^6.14.2 http-status-codes: ^2.2.0 jest: ^29.3.1 + llamaindex: 0.9.0 loglevel: ^1.8.1 mongodb: ^5.8.0 nodemailer: 6.9.9 @@ -13003,6 +13407,7 @@ __metadata: "@types/react-tabs": ^2.3.1 "@types/react-test-renderer": ^17.0.1 "@types/react-window": ^1.8.2 + "@types/react-window-infinite-loader": ^1.0.9 "@types/redux-form": ^8.1.9 "@types/redux-mock-store": ^1.0.2 "@types/shallowequal": ^1.1.5 @@ -13206,6 +13611,7 @@ __metadata: react-virtuoso: ^4.5.0 react-webcam: ^7.0.1 react-window: ^1.8.6 + react-window-infinite-loader: ^1.0.10 react-zoom-pan-pinch: ^1.6.1 redux: ^4.0.1 redux-devtools-extension: ^2.13.8 @@ -13279,6 +13685,16 @@ __metadata: languageName: node linkType: hard +"are-we-there-yet@npm:^2.0.0": + version: 2.0.0 + resolution: "are-we-there-yet@npm:2.0.0" + dependencies: + delegates: ^1.0.0 + readable-stream: ^3.6.0 + checksum: 6c80b4fd04ecee6ba6e737e0b72a4b41bdc64b7d279edfc998678567ff583c8df27e27523bc789f2c99be603ffa9eaa612803da1d886962d2086e7ff6fa90c7c + languageName: node + linkType: hard + "are-we-there-yet@npm:^3.0.0": version: 3.0.1 resolution: "are-we-there-yet@npm:3.0.1" @@ -13521,6 +13937,15 @@ __metadata: languageName: node linkType: hard +"assemblyai@npm:^4.8.0": + version: 4.9.0 + resolution: "assemblyai@npm:4.9.0" + dependencies: + ws: ^8.18.0 + checksum: b2568f37cb56fdc981b0c18a6ae45839255532c1d2be5b262126ca859949588f8959956192af9e15e4f0e8b8687b734f29545a2794aa551f579c6748a5b96fa5 + languageName: node + linkType: hard + "assert-never@npm:^1.2.1": version: 1.2.1 resolution: "assert-never@npm:1.2.1" @@ -14053,7 +14478,7 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:^1.0.2, base64-js@npm:^1.3.1": +"base64-js@npm:^1.0.2, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 @@ -14522,6 +14947,13 @@ __metadata: languageName: node linkType: hard +"bson@npm:^6.10.1": + version: 6.10.3 + resolution: "bson@npm:6.10.3" + checksum: 156807dc7a36954273cbe364783bffaaa8b89f193241d388250314f4d60b24f719d9c9fcb2d7fcbfb28f8330811617c5fd5e0b00c459867f16df6e8efe29d850 + languageName: node + linkType: hard + "buffer-crc32@npm:~0.2.3": version: 0.2.13 resolution: "buffer-crc32@npm:0.2.13" @@ -14763,6 +15195,18 @@ __metadata: languageName: node linkType: hard +"canvas@npm:^2.11.2": + version: 2.11.2 + resolution: "canvas@npm:2.11.2" + dependencies: + "@mapbox/node-pre-gyp": ^1.0.0 + nan: ^2.17.0 + node-gyp: latest + simple-get: ^3.0.3 + checksum: 61e554aef80022841dc836964534082ec21435928498032562089dfb7736215f039c7d99ee546b0cf10780232d9bf310950f8b4d489dc394e0fb6f6adfc97994 + languageName: node + linkType: hard + "capital-case@npm:^1.0.4": version: 1.0.4 resolution: "capital-case@npm:1.0.4" @@ -15314,7 +15758,7 @@ __metadata: languageName: node linkType: hard -"color-support@npm:^1.1.3": +"color-support@npm:^1.1.2, color-support@npm:^1.1.3": version: 1.1.3 resolution: "color-support@npm:1.1.3" bin: @@ -15562,7 +16006,7 @@ __metadata: languageName: node linkType: hard -"console-control-strings@npm:^1.1.0": +"console-control-strings@npm:^1.0.0, console-control-strings@npm:^1.1.0": version: 1.1.0 resolution: "console-control-strings@npm:1.1.0" checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed @@ -16207,6 +16651,13 @@ __metadata: languageName: node linkType: hard +"csv-parse@npm:^5.5.6": + version: 5.6.0 + resolution: "csv-parse@npm:5.6.0" + checksum: 173e176bdaf212bab37d0f6d39a06d039d24a1c0ee40b9f1023ebf8b36095934807deeb493c0fb58592b39b0682ccd0be5c9e8d2b137c08807e7031595ea7a51 + languageName: node + linkType: hard + "cuid@npm:^2.1.1": version: 2.1.8 resolution: "cuid@npm:2.1.8" @@ -16582,6 +17033,15 @@ __metadata: languageName: node linkType: hard +"decompress-response@npm:^4.2.0": + version: 4.2.1 + resolution: "decompress-response@npm:4.2.1" + dependencies: + mimic-response: ^2.0.0 + checksum: 4e783ca4dfe9417354d61349750fe05236f565a4415a6ca20983a311be2371debaedd9104c0b0e7b36e5f167aeaae04f84f1a0b3f8be4162f1d7d15598b8fdba + languageName: node + linkType: hard + "dedent@npm:^0.7.0": version: 0.7.0 resolution: "dedent@npm:0.7.0" @@ -16655,10 +17115,10 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:^4.0.0, deepmerge@npm:^4.2.2": - version: 4.2.2 - resolution: "deepmerge@npm:4.2.2" - checksum: a8c43a1ed8d6d1ed2b5bf569fa4c8eb9f0924034baf75d5d406e47e157a451075c4db353efea7b6bcc56ec48116a8ce72fccf867b6e078e7c561904b5897530b +"deepmerge@npm:^4.0.0, deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.1": + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 2024c6a980a1b7128084170c4cf56b0fd58a63f2da1660dcfe977415f27b17dbe5888668b59d0b063753f3220719d5e400b7f113609489c90160bb9a5518d052 languageName: node linkType: hard @@ -16871,6 +17331,13 @@ __metadata: languageName: node linkType: hard +"detect-libc@npm:^2.0.0": + version: 2.0.3 + resolution: "detect-libc@npm:2.0.3" + checksum: 2ba6a939ae55f189aea996ac67afceb650413c7a34726ee92c40fb0deb2400d57ef94631a8a3f052055eea7efb0f99a9b5e6ce923415daa3e68221f963cfc27d + languageName: node + linkType: hard + "detect-newline@npm:^3.0.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" @@ -17008,6 +17475,13 @@ __metadata: languageName: node linkType: hard +"discord-api-types@npm:^0.37.105, discord-api-types@npm:^0.37.119": + version: 0.37.119 + resolution: "discord-api-types@npm:0.37.119" + checksum: ea50d97e140e2fd0ae537281c43173e2286ef20d5781347aa2e2429da3172119badfadfbd25de2e973959324b223108c0937334fe2ec439ea4d121efd3937645 + languageName: node + linkType: hard + "dlv@npm:^1.1.3": version: 1.1.3 resolution: "dlv@npm:1.1.3" @@ -17209,7 +17683,7 @@ __metadata: languageName: node linkType: hard -"domhandler@npm:^5.0.1, domhandler@npm:^5.0.2": +"domhandler@npm:^5.0.1, domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": version: 5.0.3 resolution: "domhandler@npm:5.0.3" dependencies: @@ -17547,7 +18021,7 @@ __metadata: languageName: node linkType: hard -"entities@npm:^4.2.0, entities@npm:^4.3.0, entities@npm:^4.4.0, entities@npm:^4.5.0": +"entities@npm:^4.2.0, entities@npm:^4.4.0, entities@npm:^4.5.0": version: 4.5.0 resolution: "entities@npm:4.5.0" checksum: 853f8ebd5b425d350bffa97dd6958143179a5938352ccae092c62d1267c4e392a039be1bae7d51b6e4ffad25f51f9617531fedf5237f15df302ccfb452cbf2d7 @@ -18769,6 +19243,13 @@ __metadata: languageName: node linkType: hard +"fast-uri@npm:^3.0.1": + version: 3.0.6 + resolution: "fast-uri@npm:3.0.6" + checksum: 7161ba2a7944778d679ba8e5f00d6a2bb479a2142df0982f541d67be6c979b17808f7edbb0ce78161c85035974bde3fa52b5137df31da46c0828cb629ba67c4e + languageName: node + linkType: hard + "fast-xml-parser@npm:4.4.1": version: 4.4.1 resolution: "fast-xml-parser@npm:4.4.1" @@ -19557,6 +20038,23 @@ __metadata: languageName: node linkType: hard +"gauge@npm:^3.0.0": + version: 3.0.2 + resolution: "gauge@npm:3.0.2" + dependencies: + aproba: ^1.0.3 || ^2.0.0 + color-support: ^1.1.2 + console-control-strings: ^1.0.0 + has-unicode: ^2.0.1 + object-assign: ^4.1.1 + signal-exit: ^3.0.0 + string-width: ^4.2.3 + strip-ansi: ^6.0.1 + wide-align: ^1.1.2 + checksum: 81296c00c7410cdd48f997800155fbead4f32e4f82109be0719c63edc8560e6579946cc8abd04205297640691ec26d21b578837fd13a4e96288ab4b40b1dc3e9 + languageName: node + linkType: hard + "gauge@npm:^4.0.3": version: 4.0.4 resolution: "gauge@npm:4.0.4" @@ -19946,6 +20444,13 @@ __metadata: languageName: node linkType: hard +"gpt-tokenizer@npm:^2.6.2": + version: 2.8.1 + resolution: "gpt-tokenizer@npm:2.8.1" + checksum: 31883def85c390346f80ee01e3d9f7696089e56cbcadf69601e3f19f61c3a5ab738aa22aefb869afd963e024349b2f845c8328fe70d43107c3db1138f496b1fd + languageName: node + linkType: hard + "graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.10 resolution: "graceful-fs@npm:4.2.10" @@ -20420,6 +20925,19 @@ __metadata: languageName: node linkType: hard +"html-to-text@npm:^9.0.5": + version: 9.0.5 + resolution: "html-to-text@npm:9.0.5" + dependencies: + "@selderee/plugin-htmlparser2": ^0.11.0 + deepmerge: ^4.3.1 + dom-serializer: ^2.0.0 + htmlparser2: ^8.0.2 + selderee: ^0.11.0 + checksum: 205e0faa9b9aa281b369122acdffc5f348848e400f4037fde1fb12d68a6baa11644d2b64c3cc6821a79d3bc7316d89e85cc733d86f7f709858cb5c5b72faac65 + languageName: node + linkType: hard + "html-url-attributes@npm:^3.0.0": version: 3.0.1 resolution: "html-url-attributes@npm:3.0.1" @@ -20488,15 +21006,15 @@ __metadata: languageName: node linkType: hard -"htmlparser2@npm:^8.0.1": - version: 8.0.1 - resolution: "htmlparser2@npm:8.0.1" +"htmlparser2@npm:^8.0.1, htmlparser2@npm:^8.0.2": + version: 8.0.2 + resolution: "htmlparser2@npm:8.0.2" dependencies: domelementtype: ^2.3.0 - domhandler: ^5.0.2 + domhandler: ^5.0.3 domutils: ^3.0.1 - entities: ^4.3.0 - checksum: 06d5c71e8313597722bc429ae2a7a8333d77bd3ab07ccb916628384b37332027b047f8619448d8f4a3312b6609c6ea3302a4e77435d859e9e686999e6699ca39 + entities: ^4.4.0 + checksum: 29167a0f9282f181da8a6d0311b76820c8a59bc9e3c87009e21968264c2987d2723d6fde5a964d4b7b6cba663fca96ffb373c06d8223a85f52a6089ced942700 languageName: node linkType: hard @@ -20557,6 +21075,16 @@ __metadata: languageName: node linkType: hard +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 + languageName: node + linkType: hard + "http-proxy-middleware@npm:^2.0.3": version: 2.0.7 resolution: "http-proxy-middleware@npm:2.0.7" @@ -20621,6 +21149,16 @@ __metadata: languageName: node linkType: hard +"https-proxy-agent@npm:^7.0.0": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" + dependencies: + agent-base: ^7.1.2 + debug: 4 + checksum: b882377a120aa0544846172e5db021fa8afbf83fea2a897d397bd2ddd8095ab268c24bc462f40a15f2a8c600bf4aa05ce52927f70038d4014e68aefecfa94e8d + languageName: node + linkType: hard + "human-signals@npm:^1.1.1": version: 1.1.1 resolution: "human-signals@npm:1.1.1" @@ -22694,6 +23232,13 @@ __metadata: languageName: node linkType: hard +"jsbi@npm:^4.3.0": + version: 4.3.0 + resolution: "jsbi@npm:4.3.0" + checksum: 27c4f178eb7fd9d1756144066fdebc62f4a0176e877f55e646e8ce84075c13551bd575a316b9959ccdcca9d5dc05a81c9907cfa09f0cfeb43c9777797e36b0e9 + languageName: node + linkType: hard + "jsbn@npm:1.1.0": version: 1.1.0 resolution: "jsbn@npm:1.1.0" @@ -23055,6 +23600,13 @@ __metadata: languageName: node linkType: hard +"leac@npm:^0.6.0": + version: 0.6.0 + resolution: "leac@npm:0.6.0" + checksum: a7a722cfc2ddfd6fb2620e5dee3ac8e9b0af4eb04325f3c8286a820de78becba3010a4d7026ff5189bb159eb7a851c3a1ac73e076eb0d54fcee0adaf695291ba + languageName: node + linkType: hard + "leven@npm:^3.1.0": version: 3.1.0 resolution: "leven@npm:3.1.0" @@ -23212,6 +23764,25 @@ __metadata: languageName: node linkType: hard +"llamaindex@npm:0.9.0": + version: 0.9.0 + resolution: "llamaindex@npm:0.9.0" + dependencies: + "@llamaindex/cloud": 3.0.0 + "@llamaindex/core": 0.5.0 + "@llamaindex/env": 0.1.27 + "@llamaindex/node-parser": 1.0.0 + "@llamaindex/openai": 0.1.52 + "@types/lodash": ^4.17.7 + "@types/node": ^22.9.0 + ajv: ^8.17.1 + gpt-tokenizer: ^2.6.2 + lodash: ^4.17.21 + magic-bytes.js: ^1.10.0 + checksum: fb8f78559ba4ad491614ff712d650d01ad926215396942c0ca328d988958c1c7af7e9c4149d856429e0d399ad1b5c3099851d1c5e141537b22fd103064865770 + languageName: node + linkType: hard + "load-script@npm:^1.0.0": version: 1.0.0 resolution: "load-script@npm:1.0.0" @@ -23512,14 +24083,14 @@ __metadata: languageName: node linkType: hard -"lop@npm:^0.4.1": - version: 0.4.1 - resolution: "lop@npm:0.4.1" +"lop@npm:^0.4.2": + version: 0.4.2 + resolution: "lop@npm:0.4.2" dependencies: duck: ^0.1.12 option: ~0.2.1 underscore: ^1.13.1 - checksum: 0586a2601a6cc709664b40e69266fb684136d9f4041a97d76413030846f0c03f36c6a262873efbcf6ab8e5a584449e24b18722b8a7e5d58e5326359f0be08439 + checksum: 4a21fa77b8f040d032805940ef10c025b1a8a62ce4b0cd87e10bc2ef9cf2f86dca7e62790c3d1ce0b23365c1fd9e9209b75df7581c2f6576b85a1d5559c906e6 languageName: node linkType: hard @@ -23588,6 +24159,13 @@ __metadata: languageName: node linkType: hard +"magic-bytes.js@npm:^1.10.0": + version: 1.10.0 + resolution: "magic-bytes.js@npm:1.10.0" + checksum: c10e7fc3fe584e4b0767554fb6a12dfc4a9db0782d5005cbdd46bc9b36a8bb420f5266a4b02e089ea4db587937fde289ea467a7a379ad969fb906bf4a0ec3f38 + languageName: node + linkType: hard + "magic-string@npm:^0.25.0, magic-string@npm:^0.25.7": version: 0.25.9 resolution: "magic-string@npm:0.25.9" @@ -23683,22 +24261,23 @@ __metadata: languageName: node linkType: hard -"mammoth@npm:^1.5.1": - version: 1.5.1 - resolution: "mammoth@npm:1.5.1" +"mammoth@npm:^1.5.1, mammoth@npm:^1.7.2": + version: 1.9.0 + resolution: "mammoth@npm:1.9.0" dependencies: + "@xmldom/xmldom": ^0.8.6 argparse: ~1.0.3 + base64-js: ^1.5.1 bluebird: ~3.4.0 dingbat-to-unicode: ^1.0.1 jszip: ^3.7.1 - lop: ^0.4.1 + lop: ^0.4.2 path-is-absolute: ^1.0.0 - sax: ~1.1.1 underscore: ^1.13.1 xmlbuilder: ^10.0.0 bin: mammoth: bin/mammoth - checksum: a780a80fd87c812de3d882fa8aa7bf54d59854bbe7195ccf90e3b63ef901de3a9e7ca664d7367ae5b638a9d8feb1376c6de9026a671a2f38e049297e0d9b41a4 + checksum: d9526970fa95a75798ec992e98865678c71f489525d54517d0316c5a2954341cacbf9e629d9467bd0a40892a1b937755ce8c6b66e46c9ff2e95a00a612e07b8f languageName: node linkType: hard @@ -23748,6 +24327,13 @@ __metadata: languageName: node linkType: hard +"md-utils-ts@npm:^2.0.0": + version: 2.0.0 + resolution: "md-utils-ts@npm:2.0.0" + checksum: 587eeb888464af58450cc28516171c2fefc298970b5bb75bbcd9ecad4637e747dc4949d944b99418bd8da207b0f954566e5b95d316a000c60044771ef1150627 + languageName: node + linkType: hard + "md5.js@npm:^1.3.4": version: 1.3.5 resolution: "md5.js@npm:1.3.5" @@ -24521,6 +25107,13 @@ __metadata: languageName: node linkType: hard +"mimic-response@npm:^2.0.0": + version: 2.1.0 + resolution: "mimic-response@npm:2.1.0" + checksum: 014fad6ab936657e5f2f48bd87af62a8e928ebe84472aaf9e14fec4fcb31257a5edff77324d8ac13ddc6685ba5135cf16e381efac324e5f174fb4ddbf902bf07 + languageName: node + linkType: hard + "min-indent@npm:^1.0.0, min-indent@npm:^1.0.1": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -24841,6 +25434,16 @@ __metadata: languageName: node linkType: hard +"mongodb-connection-string-url@npm:^3.0.0": + version: 3.0.2 + resolution: "mongodb-connection-string-url@npm:3.0.2" + dependencies: + "@types/whatwg-url": ^11.0.2 + whatwg-url: ^14.1.0 || ^13.0.0 + checksum: 382319aa41d381ff4be9370024e3cf765ded14aa581bca7c7a171fcaae618b8d92912329b6b13898334c3b6f3cab12ae8785defad2745ca20226ceeb253ef1ae + languageName: node + linkType: hard + "mongodb@npm:^5.8.0": version: 5.9.2 resolution: "mongodb@npm:5.9.2" @@ -24873,6 +25476,40 @@ __metadata: languageName: node linkType: hard +"mongodb@npm:^6.7.0": + version: 6.13.0 + resolution: "mongodb@npm:6.13.0" + dependencies: + "@mongodb-js/saslprep": ^1.1.9 + bson: ^6.10.1 + mongodb-connection-string-url: ^3.0.0 + peerDependencies: + "@aws-sdk/credential-providers": ^3.188.0 + "@mongodb-js/zstd": ^1.1.0 || ^2.0.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: ">=6.0.0 <7" + snappy: ^7.2.2 + socks: ^2.7.1 + peerDependenciesMeta: + "@aws-sdk/credential-providers": + optional: true + "@mongodb-js/zstd": + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + checksum: 1971fa021b79769427b93941788c3e9db301b2bd7444869b0ac0331d58a5a40bea361c5d8526e9983a8b1ee2e5bb783dffa939c6a36f512edf0009cdf409e020 + languageName: node + linkType: hard + "moo-color@npm:^1.0.2": version: 1.0.2 resolution: "moo-color@npm:1.0.2" @@ -24996,6 +25633,15 @@ __metadata: languageName: node linkType: hard +"nan@npm:^2.17.0": + version: 2.22.0 + resolution: "nan@npm:2.22.0" + dependencies: + node-gyp: latest + checksum: 222e3a090e326c72f6782d948f44ee9b81cfb2161d5fe53216f04426a273fd094deee9dcc6813096dd2397689a2b10c1a92d3885d2e73fd2488a51547beb2929 + languageName: node + linkType: hard + "nanoid@npm:^2.0.4": version: 2.1.11 resolution: "nanoid@npm:2.1.11" @@ -25205,6 +25851,17 @@ __metadata: languageName: node linkType: hard +"nopt@npm:^5.0.0": + version: 5.0.0 + resolution: "nopt@npm:5.0.0" + dependencies: + abbrev: 1 + bin: + nopt: bin/nopt.js + checksum: d35fdec187269503843924e0114c0c6533fb54bbf1620d0f28b4b60ba01712d6687f62565c55cc20a504eff0fbe5c63e22340c3fad549ad40469ffb611b04f2f + languageName: node + linkType: hard + "nopt@npm:^6.0.0": version: 6.0.0 resolution: "nopt@npm:6.0.0" @@ -25263,6 +25920,16 @@ __metadata: languageName: node linkType: hard +"notion-md-crawler@npm:^1.0.0": + version: 1.0.1 + resolution: "notion-md-crawler@npm:1.0.1" + dependencies: + "@notionhq/client": ^2.2.15 + md-utils-ts: ^2.0.0 + checksum: 668ef389c7c4e35de842faa4d1c8481f9e675a2ed68b1ad01f1fc1a4fdc2e9f4eca29f9234f69f28f569986655504ecd5fa36be4bedd845fd320409a3391241c + languageName: node + linkType: hard + "npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" @@ -25281,6 +25948,18 @@ __metadata: languageName: node linkType: hard +"npmlog@npm:^5.0.1": + version: 5.0.1 + resolution: "npmlog@npm:5.0.1" + dependencies: + are-we-there-yet: ^2.0.0 + console-control-strings: ^1.1.0 + gauge: ^3.0.0 + set-blocking: ^2.0.0 + checksum: 516b2663028761f062d13e8beb3f00069c5664925871a9b57989642ebe09f23ab02145bf3ab88da7866c4e112cafff72401f61a672c7c8a20edc585a7016ef5f + languageName: node + linkType: hard + "npmlog@npm:^6.0.0": version: 6.0.2 resolution: "npmlog@npm:6.0.2" @@ -25588,9 +26267,9 @@ __metadata: languageName: node linkType: hard -"openai@npm:^4.64.0": - version: 4.67.0 - resolution: "openai@npm:4.67.0" +"openai@npm:^4.64.0, openai@npm:^4.83.0": + version: 4.85.2 + resolution: "openai@npm:4.85.2" dependencies: "@types/node": ^18.11.18 "@types/node-fetch": ^2.6.4 @@ -25600,13 +26279,16 @@ __metadata: formdata-node: ^4.3.2 node-fetch: ^2.6.7 peerDependencies: + ws: ^8.18.0 zod: ^3.23.8 peerDependenciesMeta: + ws: + optional: true zod: optional: true bin: openai: bin/cli - checksum: 9e214f27630d1cb0ae9bf129a81133e6cf4683e7af8e8aa852cf473d9a1a84c6f551722b0557c7c18c8b92ee0112f1781227b89e9b7f16be9de1b64fcba4c55e + checksum: 44686ce3e6b67a6374a8e30e65c638bff901f48f2df539c862f3bb86e6f079e4c30804f0141c2dfe91fc4714cd37cbe67900c0de1476ecb950db8b78fe8f69b7 languageName: node linkType: hard @@ -25841,6 +26523,13 @@ __metadata: languageName: node linkType: hard +"papaparse@npm:^5.4.1": + version: 5.5.2 + resolution: "papaparse@npm:5.5.2" + checksum: 59d5c6aca4fe1621cc12f66c024d0ea651bb4aad77d50c2d66a3e3c1ba60e992e2f52762f783fc2531348120c302ab272d8e448d853652232c9c742cdb666fb8 + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -25959,6 +26648,16 @@ __metadata: languageName: node linkType: hard +"parseley@npm:^0.12.0": + version: 0.12.1 + resolution: "parseley@npm:0.12.1" + dependencies: + leac: ^0.6.0 + peberminta: ^0.9.0 + checksum: 147760bce6c4a4f8c62af021a84ced262f078f60a1119e6891eba69567a953e06295ad2c70e5e89892ad1d4af0126f0856742d657a19a29ebf58422cf3bfd4f3 + languageName: node + linkType: hard + "parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -26142,6 +26841,13 @@ __metadata: languageName: node linkType: hard +"peberminta@npm:^0.9.0": + version: 0.9.0 + resolution: "peberminta@npm:0.9.0" + checksum: b983b68077269ca8a3327520a0a3f027fa930faa9fb3cb53bed1cb3847ebc0ed55db936d70b1745a756149911f5f450e898e87e25ab207f1b8b892bed48fb540 + languageName: node + linkType: hard + "pend@npm:~1.2.0": version: 1.2.0 resolution: "pend@npm:1.2.0" @@ -27445,6 +28151,13 @@ __metadata: languageName: node linkType: hard +"priorityqueuejs@npm:^2.0.0": + version: 2.0.0 + resolution: "priorityqueuejs@npm:2.0.0" + checksum: 37d5e6679811a5b9bc68cfbdc7b20b83b02ec8028b2d534019e6e99c14d4ef91fc8c7640de1501482ee029f84961eefe096ea5652f9cc93b12fec4456d961f71 + languageName: node + linkType: hard + "prismjs@npm:^1.27.0, prismjs@npm:~1.27.0": version: 1.27.0 resolution: "prismjs@npm:1.27.0" @@ -27659,10 +28372,10 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.1.1": - version: 2.1.1 - resolution: "punycode@npm:2.1.1" - checksum: 823bf443c6dd14f669984dea25757b37993f67e8d94698996064035edd43bed8a5a17a9f12e439c2b35df1078c6bec05a6c86e336209eb1061e8025c481168e8 +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 languageName: node linkType: hard @@ -28069,90 +28782,98 @@ __metadata: languageName: node linkType: hard -"react-aria-components@npm:^1.2.1, react-aria-components@npm:^1.3.3": - version: 1.3.3 - resolution: "react-aria-components@npm:1.3.3" +"react-aria-components@npm:^1.3.3, react-aria-components@npm:^1.6.0": + version: 1.6.0 + resolution: "react-aria-components@npm:1.6.0" dependencies: - "@internationalized/date": ^3.5.5 - "@internationalized/string": ^3.2.3 - "@react-aria/collections": 3.0.0-alpha.4 - "@react-aria/color": 3.0.0-rc.2 - "@react-aria/dnd": ^3.7.2 - "@react-aria/focus": ^3.18.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/menu": ^3.15.3 - "@react-aria/toolbar": 3.0.0-beta.8 - "@react-aria/tree": 3.0.0-alpha.5 - "@react-aria/utils": ^3.25.2 - "@react-aria/virtualizer": ^4.0.2 - "@react-stately/color": ^3.7.2 - "@react-stately/layout": ^4.0.2 - "@react-stately/menu": ^3.8.2 - "@react-stately/table": ^3.12.2 - "@react-stately/utils": ^3.10.3 - "@react-stately/virtualizer": ^4.0.2 - "@react-types/color": 3.0.0-rc.1 - "@react-types/form": ^3.7.6 - "@react-types/grid": ^3.2.8 - "@react-types/shared": ^3.24.1 - "@react-types/table": ^3.10.1 + "@internationalized/date": ^3.7.0 + "@internationalized/string": ^3.2.5 + "@react-aria/autocomplete": 3.0.0-alpha.37 + "@react-aria/collections": 3.0.0-alpha.7 + "@react-aria/color": ^3.0.3 + "@react-aria/disclosure": ^3.0.1 + "@react-aria/dnd": ^3.8.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/interactions": ^3.23.0 + "@react-aria/live-announcer": ^3.4.1 + "@react-aria/menu": ^3.17.0 + "@react-aria/toolbar": 3.0.0-beta.12 + "@react-aria/tree": 3.0.0-beta.3 + "@react-aria/utils": ^3.27.0 + "@react-aria/virtualizer": ^4.1.1 + "@react-stately/autocomplete": 3.0.0-alpha.0 + "@react-stately/color": ^3.8.2 + "@react-stately/disclosure": ^3.0.1 + "@react-stately/layout": ^4.1.1 + "@react-stately/menu": ^3.9.1 + "@react-stately/selection": ^3.19.0 + "@react-stately/table": ^3.13.1 + "@react-stately/utils": ^3.10.5 + "@react-stately/virtualizer": ^4.2.1 + "@react-types/color": ^3.0.2 + "@react-types/form": ^3.7.9 + "@react-types/grid": ^3.2.11 + "@react-types/shared": ^3.27.0 + "@react-types/table": ^3.10.4 "@swc/helpers": ^0.5.0 client-only: ^0.0.1 - react-aria: ^3.34.3 - react-stately: ^3.32.2 + react-aria: ^3.37.0 + react-stately: ^3.35.0 use-sync-external-store: ^1.2.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 094e4b9f93e48a07280f82d0fc93a29fcfd5587fb399d8ff5b69a08058fa6f34a3b0b16bcc50fe212150b146dd75a043be5d5c078af11d6bbe05db554e624d4c + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 6bf508e84ca715b13f5dc16c635d3e4986c4af22a8bda95002cc178f621468037c2f5cb70ee141dc084230d06b0a34a6f5f6b0890cd17e39757592f836e758e0 languageName: node linkType: hard -"react-aria@npm:^3.34.3": - version: 3.34.3 - resolution: "react-aria@npm:3.34.3" +"react-aria@npm:^3.37.0": + version: 3.37.0 + resolution: "react-aria@npm:3.37.0" dependencies: - "@internationalized/string": ^3.2.3 - "@react-aria/breadcrumbs": ^3.5.16 - "@react-aria/button": ^3.9.8 - "@react-aria/calendar": ^3.5.11 - "@react-aria/checkbox": ^3.14.6 - "@react-aria/combobox": ^3.10.3 - "@react-aria/datepicker": ^3.11.2 - "@react-aria/dialog": ^3.5.17 - "@react-aria/dnd": ^3.7.2 - "@react-aria/focus": ^3.18.2 - "@react-aria/gridlist": ^3.9.3 - "@react-aria/i18n": ^3.12.2 - "@react-aria/interactions": ^3.22.2 - "@react-aria/label": ^3.7.11 - "@react-aria/link": ^3.7.4 - "@react-aria/listbox": ^3.13.3 - "@react-aria/menu": ^3.15.3 - "@react-aria/meter": ^3.4.16 - "@react-aria/numberfield": ^3.11.6 - "@react-aria/overlays": ^3.23.2 - "@react-aria/progress": ^3.4.16 - "@react-aria/radio": ^3.10.7 - "@react-aria/searchfield": ^3.7.8 - "@react-aria/select": ^3.14.9 - "@react-aria/selection": ^3.19.3 - "@react-aria/separator": ^3.4.2 - "@react-aria/slider": ^3.7.11 - "@react-aria/ssr": ^3.9.5 - "@react-aria/switch": ^3.6.7 - "@react-aria/table": ^3.15.3 - "@react-aria/tabs": ^3.9.5 - "@react-aria/tag": ^3.4.5 - "@react-aria/textfield": ^3.14.8 - "@react-aria/tooltip": ^3.7.7 - "@react-aria/utils": ^3.25.2 - "@react-aria/visually-hidden": ^3.8.15 - "@react-types/shared": ^3.24.1 + "@internationalized/string": ^3.2.5 + "@react-aria/breadcrumbs": ^3.5.20 + "@react-aria/button": ^3.11.1 + "@react-aria/calendar": ^3.7.0 + "@react-aria/checkbox": ^3.15.1 + "@react-aria/color": ^3.0.3 + "@react-aria/combobox": ^3.11.1 + "@react-aria/datepicker": ^3.13.0 + "@react-aria/dialog": ^3.5.21 + "@react-aria/disclosure": ^3.0.1 + "@react-aria/dnd": ^3.8.1 + "@react-aria/focus": ^3.19.1 + "@react-aria/gridlist": ^3.10.1 + "@react-aria/i18n": ^3.12.5 + "@react-aria/interactions": ^3.23.0 + "@react-aria/label": ^3.7.14 + "@react-aria/link": ^3.7.8 + "@react-aria/listbox": ^3.14.0 + "@react-aria/menu": ^3.17.0 + "@react-aria/meter": ^3.4.19 + "@react-aria/numberfield": ^3.11.10 + "@react-aria/overlays": ^3.25.0 + "@react-aria/progress": ^3.4.19 + "@react-aria/radio": ^3.10.11 + "@react-aria/searchfield": ^3.8.0 + "@react-aria/select": ^3.15.1 + "@react-aria/selection": ^3.22.0 + "@react-aria/separator": ^3.4.5 + "@react-aria/slider": ^3.7.15 + "@react-aria/ssr": ^3.9.7 + "@react-aria/switch": ^3.6.11 + "@react-aria/table": ^3.16.1 + "@react-aria/tabs": ^3.9.9 + "@react-aria/tag": ^3.4.9 + "@react-aria/textfield": ^3.16.0 + "@react-aria/tooltip": ^3.7.11 + "@react-aria/utils": ^3.27.0 + "@react-aria/visually-hidden": ^3.8.19 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 796769d4d5bd7070e3c603d434b3b959a5c7c7c724fff9c589cef1830521039eddb83e042eab14795be8c4a00c1ddcd2823cb8304496815d52bd3929fbb86172 + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: e7bbfc4dae05f085507700ffae7ecd2d4b197b48a652bde1b98288c367d0efa3980424b41c6251f686cb7a86d2be61ffb0677f86930626fe880f260ea6524c3e languageName: node linkType: hard @@ -28808,36 +29529,38 @@ __metadata: languageName: node linkType: hard -"react-stately@npm:^3.32.2": - version: 3.32.2 - resolution: "react-stately@npm:3.32.2" - dependencies: - "@react-stately/calendar": ^3.5.4 - "@react-stately/checkbox": ^3.6.8 - "@react-stately/collections": ^3.10.9 - "@react-stately/combobox": ^3.9.2 - "@react-stately/data": ^3.11.6 - "@react-stately/datepicker": ^3.10.2 - "@react-stately/dnd": ^3.4.2 - "@react-stately/form": ^3.0.5 - "@react-stately/list": ^3.10.8 - "@react-stately/menu": ^3.8.2 - "@react-stately/numberfield": ^3.9.6 - "@react-stately/overlays": ^3.6.10 - "@react-stately/radio": ^3.10.7 - "@react-stately/searchfield": ^3.5.6 - "@react-stately/select": ^3.6.7 - "@react-stately/selection": ^3.16.2 - "@react-stately/slider": ^3.5.7 - "@react-stately/table": ^3.12.2 - "@react-stately/tabs": ^3.6.9 - "@react-stately/toggle": ^3.7.7 - "@react-stately/tooltip": ^3.4.12 - "@react-stately/tree": ^3.8.4 - "@react-types/shared": ^3.24.1 +"react-stately@npm:^3.35.0": + version: 3.35.0 + resolution: "react-stately@npm:3.35.0" + dependencies: + "@react-stately/calendar": ^3.7.0 + "@react-stately/checkbox": ^3.6.11 + "@react-stately/collections": ^3.12.1 + "@react-stately/color": ^3.8.2 + "@react-stately/combobox": ^3.10.2 + "@react-stately/data": ^3.12.1 + "@react-stately/datepicker": ^3.12.0 + "@react-stately/disclosure": ^3.0.1 + "@react-stately/dnd": ^3.5.1 + "@react-stately/form": ^3.1.1 + "@react-stately/list": ^3.11.2 + "@react-stately/menu": ^3.9.1 + "@react-stately/numberfield": ^3.9.9 + "@react-stately/overlays": ^3.6.13 + "@react-stately/radio": ^3.10.10 + "@react-stately/searchfield": ^3.5.9 + "@react-stately/select": ^3.6.10 + "@react-stately/selection": ^3.19.0 + "@react-stately/slider": ^3.6.1 + "@react-stately/table": ^3.13.1 + "@react-stately/tabs": ^3.7.1 + "@react-stately/toggle": ^3.8.1 + "@react-stately/tooltip": ^3.5.1 + "@react-stately/tree": ^3.8.7 + "@react-types/shared": ^3.27.0 peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - checksum: 60678fe543baa4c74f338317183c4ef6112353ed86c2d1f8c0f62df5fd3fa624af6cd8006d7e2f7f2c2ae60dfe86c7454f2ce6f5dff58cf8281abd64cd97bcea + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: cb01501b862ccc0426241d699742cd90aeec7e26d440f628ba159ab70a3560a25af678e0da226d1cbe8d99cb3c32fc382c1c875d3171a4fb4c514654e16a83e1 languageName: node linkType: hard @@ -29019,6 +29742,16 @@ __metadata: languageName: node linkType: hard +"react-window-infinite-loader@npm:^1.0.10": + version: 1.0.10 + resolution: "react-window-infinite-loader@npm:1.0.10" + peerDependencies: + react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 3ee79ce325e45a7d4d9f92c13e7ff4c523578fa454de3a440980b286d964eb951095c012a7f43ca75e9d86ed2b052c81b08134dfa8827144f44b059cc56514c3 + languageName: node + linkType: hard + "react-window@npm:^1.8.6": version: 1.8.8 resolution: "react-window@npm:1.8.8" @@ -30131,13 +30864,6 @@ __metadata: languageName: node linkType: hard -"sax@npm:~1.1.1": - version: 1.1.6 - resolution: "sax@npm:1.1.6" - checksum: 879f18483d00f4630580fb4dc95da7d06046b1d71af1f27e33425f81d82751ab66a84eb584a462aa610f7a94de8d87416e03c708530ba76b1aa381b6828bfc9e - languageName: node - linkType: hard - "sax@npm:~1.2.4": version: 1.2.4 resolution: "sax@npm:1.2.4" @@ -30237,6 +30963,15 @@ __metadata: languageName: node linkType: hard +"selderee@npm:^0.11.0": + version: 0.11.0 + resolution: "selderee@npm:0.11.0" + dependencies: + parseley: ^0.12.0 + checksum: af8a68c1f4cde858152943b6fc9f2b7164c8fb1a1c9f01b44350dffd1f79783930d77a0ae33548a036816d17c8130eeb9d15f1db65c9262ca368ad3a0d750f66 + languageName: node + linkType: hard + "select-hose@npm:^2.0.0": version: 2.0.0 resolution: "select-hose@npm:2.0.0" @@ -30253,6 +30988,13 @@ __metadata: languageName: node linkType: hard +"semaphore@npm:^1.1.0": + version: 1.1.0 + resolution: "semaphore@npm:1.1.0" + checksum: d2445d232ad9959048d4748ef54eb01bc7b60436be2b42fb7de20c4cffacf70eafeeecd3772c1baf408cfdce3805fa6618a4389590335671f18cde54ef3cfae4 + languageName: node + linkType: hard + "semver@npm:2 || 3 || 4 || 5, semver@npm:^5.6.0": version: 5.7.2 resolution: "semver@npm:5.7.2" @@ -30524,7 +31266,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -30552,6 +31294,17 @@ __metadata: languageName: node linkType: hard +"simple-get@npm:^3.0.3": + version: 3.1.1 + resolution: "simple-get@npm:3.1.1" + dependencies: + decompress-response: ^4.2.0 + once: ^1.3.1 + simple-concat: ^1.0.0 + checksum: 80195e70bf171486e75c31e28e5485468195cc42f85940f8b45c4a68472160144d223eb4d07bc82ef80cb974b7c401db021a540deb2d34ac4b3b8883da2d6401 + languageName: node + linkType: hard + "simplebar-react@npm:^2.4.3": version: 2.4.3 resolution: "simplebar-react@npm:2.4.3" @@ -32136,6 +32889,15 @@ __metadata: languageName: node linkType: hard +"tr46@npm:^5.0.0": + version: 5.0.0 + resolution: "tr46@npm:5.0.0" + dependencies: + punycode: ^2.3.1 + checksum: 8d8b021f8e17675ebf9e672c224b6b6cfdb0d5b92141349e9665c14a2501c54a298d11264bbb0b17b447581e1e83d4fc3c038c929f3d210e3964d4be47460288 + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -32367,7 +33129,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2": +"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: e4aba30e632b8c8902b47587fd13345e2827fa639e7c3121074d5ee0880723282411a8838f830b55100cbe4517672f84a2472667d355b81e8af165a55dc6203a @@ -32706,6 +33468,20 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.20.0": + version: 6.20.0 + resolution: "undici-types@npm:6.20.0" + checksum: b7bc50f012dc6afbcce56c9fd62d7e86b20a62ff21f12b7b5cbf1973b9578d90f22a9c7fe50e638e96905d33893bf2f9f16d98929c4673c2480de05c6c96ea8b + languageName: node + linkType: hard + +"undici@npm:6.21.1": + version: 6.21.1 + resolution: "undici@npm:6.21.1" + checksum: 2efc52f77224754a2efa7cb6459829f3c93c8321d17e76f574a904b353783d95073b6116f5b15637c4845d98c9dc5a019b809cb9d63b3529267e7727c49f6996 + languageName: node + linkType: hard + "unescape-js@npm:^1.1.4": version: 1.1.4 resolution: "unescape-js@npm:1.1.4" @@ -32894,6 +33670,18 @@ __metadata: languageName: node linkType: hard +"unpdf@npm:^0.12.1": + version: 0.12.1 + resolution: "unpdf@npm:0.12.1" + dependencies: + canvas: ^2.11.2 + dependenciesMeta: + canvas: + optional: true + checksum: 13263082332ddb5ce796c9d2c58203e4e9a14ba2f85e313fb5b2f9efb7b706d6510ca6ec657607de26704e897008d6b606150d71aa18ee0054fb6aa1da150c09 + languageName: node + linkType: hard + "unpipe@npm:1.0.0, unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" @@ -33683,6 +34471,16 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^14.1.0 || ^13.0.0": + version: 14.1.1 + resolution: "whatwg-url@npm:14.1.1" + dependencies: + tr46: ^5.0.0 + webidl-conversions: ^7.0.0 + checksum: d44667005e35b545587b49371e0c75ddc6355407c07d9c6aaafc01d8ed3dfadf44393fa74c74cda3d8d5f41d3860acf408b4e81820c6de7cc5a17d9eb274349f + languageName: node + linkType: hard + "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -33791,7 +34589,7 @@ __metadata: languageName: node linkType: hard -"wide-align@npm:^1.1.5": +"wide-align@npm:^1.1.2, wide-align@npm:^1.1.5": version: 1.1.5 resolution: "wide-align@npm:1.1.5" dependencies: @@ -34137,7 +34935,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0, ws@npm:^8.2.3, ws@npm:^8.4.2": +"ws@npm:^8.11.0, ws@npm:^8.18.0, ws@npm:^8.2.3, ws@npm:^8.4.2": version: 8.18.0 resolution: "ws@npm:8.18.0" peerDependencies: @@ -34409,6 +35207,15 @@ __metadata: languageName: node linkType: hard +"zod-to-json-schema@npm:^3.23.3": + version: 3.24.2 + resolution: "zod-to-json-schema@npm:3.24.2" + peerDependencies: + zod: ^3.24.1 + checksum: 1edcf680c4938f99a7b9df5b0d5eb3a3eb2f2cc57d4d0dbe5cc34539c104443a8498bb225a43fd3a848f117205027cd20f4ea8324fdb1e4aede8433fc1595ee9 + languageName: node + linkType: hard + "zod-validation-error@npm:^3.0.3": version: 3.4.0 resolution: "zod-validation-error@npm:3.4.0" @@ -34418,10 +35225,10 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.22.4": - version: 3.23.8 - resolution: "zod@npm:3.23.8" - checksum: 15949ff82118f59c893dacd9d3c766d02b6fa2e71cf474d5aa888570c469dbf5446ac5ad562bb035bf7ac9650da94f290655c194f4a6de3e766f43febd432c5c +"zod@npm:^3.22.4, zod@npm:^3.23.8": + version: 3.24.2 + resolution: "zod@npm:3.24.2" + checksum: c02455c09678c5055c636d64f9fcda2424fea0aa46ac7d9681e7f41990bc55f488bcd84b9d7cfef0f6e906f51f55b245239d92a9f726248aa74c5b84edf00c2d languageName: node linkType: hard diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java index 413720c5e483..297ac13544cc 100644 --- a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java +++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java @@ -6,6 +6,7 @@ import com.appsmith.external.git.FileInterface; import com.appsmith.external.git.GitExecutor; import com.appsmith.external.git.constants.GitSpan; +import com.appsmith.external.git.handler.FSGitHandler; import com.appsmith.external.git.models.GitResourceIdentity; import com.appsmith.external.git.models.GitResourceMap; import com.appsmith.external.git.models.GitResourceType; @@ -75,6 +76,7 @@ import static com.appsmith.git.constants.GitDirectories.DATASOURCE_DIRECTORY; import static com.appsmith.git.constants.GitDirectories.JS_LIB_DIRECTORY; import static com.appsmith.git.constants.GitDirectories.PAGE_DIRECTORY; +import static com.appsmith.git.constants.ce.CommonConstantsCE.DELIMITER_PATH; @Slf4j @Getter @@ -83,6 +85,7 @@ public class FileUtilsCEImpl implements FileInterface { private final GitServiceConfig gitServiceConfig; + protected final FSGitHandler fsGitHandler; private final GitExecutor gitExecutor; protected final FileOperations fileOperations; private final ObservationHelper observationHelper; @@ -101,11 +104,13 @@ public class FileUtilsCEImpl implements FileInterface { public FileUtilsCEImpl( GitServiceConfig gitServiceConfig, + FSGitHandler fsGitHandler, GitExecutor gitExecutor, FileOperations fileOperations, ObservationHelper observationHelper, ObjectMapper objectMapper) { this.gitServiceConfig = gitServiceConfig; + this.fsGitHandler = fsGitHandler; this.gitExecutor = gitExecutor; this.fileOperations = fileOperations; this.observationHelper = observationHelper; @@ -247,7 +252,7 @@ public Mono saveArtifactToGitRepo(Path baseRepoSuffix, GitResourceMap gitR // Repo path will be: // baseRepo : root/workspaceId/defaultAppId/repoName/{applicationData} // Checkout to mentioned branch if not already checked-out - return gitExecutor + return fsGitHandler .resetToLastCommit(baseRepoSuffix, branchName) .flatMap(isSwitched -> { Path baseRepo = Paths.get(gitServiceConfig.getGitRootPath()).resolve(baseRepoSuffix); @@ -263,12 +268,48 @@ public Mono saveArtifactToGitRepo(Path baseRepoSuffix, GitResourceMap gitR .subscribeOn(scheduler); } + protected Set getWhitelistedPaths() { + String pages = PAGE_DIRECTORY + DELIMITER_PATH; + String datasources = DATASOURCE_DIRECTORY + DELIMITER_PATH; + String themes = CommonConstants.THEME + JSON_EXTENSION; + String application = CommonConstants.APPLICATION + JSON_EXTENSION; + String metadata = CommonConstants.METADATA + JSON_EXTENSION; + String customJsLibs = JS_LIB_DIRECTORY + DELIMITER_PATH; + + return new HashSet<>(Set.of(pages, datasources, themes, application, metadata, customJsLibs)); + } + + protected Boolean isWhiteListedPath(Set whiteListedPaths, String relativePath) { + + // Not expecting the relative path to ever be empty. + // .git is internal file this shouldn't be whitelisted + if (!StringUtils.hasText(relativePath) || relativePath.contains(".git/")) { + return Boolean.FALSE; + } + + // cases where the path is a direct root config object + if (whiteListedPaths.contains(relativePath)) { + return Boolean.TRUE; + } + + String[] tokens = relativePath.strip().split(DELIMITER_PATH); + // it means that path is not a root config object and adheres to the given whitelisted path + if (tokens.length > 1 && whiteListedPaths.contains(tokens[0] + DELIMITER_PATH)) { + return Boolean.TRUE; + } + + return Boolean.FALSE; + } + protected Set getExistingFilesInRepo(Path baseRepo) throws IOException { + Set whiteListedPaths = getWhitelistedPaths(); try (Stream stream = Files.walk(baseRepo).parallel()) { return stream.filter(path -> { try { - return !path.toString().contains(".git" + File.separator) - && (Files.isRegularFile(path) || FileUtils.isEmptyDirectory(path.toFile())); + return (Files.isRegularFile(path) || FileUtils.isEmptyDirectory(path.toFile())) + && isWhiteListedPath( + whiteListedPaths, + baseRepo.relativize(path).toString()); } catch (IOException e) { log.error("Unable to find file details. Please check the file at file path: {}", path); log.error("Assuming that it does not exist for now ..."); diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java index 34256a08096a..9122b5d7c3dc 100644 --- a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java +++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java @@ -2,6 +2,7 @@ import com.appsmith.external.git.FileInterface; import com.appsmith.external.git.GitExecutor; +import com.appsmith.external.git.handler.FSGitHandler; import com.appsmith.external.git.operations.FileOperations; import com.appsmith.external.helpers.ObservationHelper; import com.appsmith.git.configurations.GitServiceConfig; @@ -21,10 +22,11 @@ public class FileUtilsImpl extends FileUtilsCEImpl implements FileInterface { public FileUtilsImpl( GitServiceConfig gitServiceConfig, + FSGitHandler fsGitHandler, GitExecutor gitExecutor, FileOperations fileOperations, ObservationHelper observationHelper, ObjectMapper objectMapper) { - super(gitServiceConfig, gitExecutor, fileOperations, observationHelper, objectMapper); + super(gitServiceConfig, fsGitHandler, gitExecutor, fileOperations, observationHelper, objectMapper); } } diff --git a/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java b/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java index e222feff2a92..144fee83a010 100644 --- a/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java +++ b/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java @@ -1,5 +1,6 @@ package com.appsmith.git.helpers; +import com.appsmith.external.git.handler.FSGitHandler; import com.appsmith.external.git.operations.FileOperations; import com.appsmith.external.helpers.ObservationHelper; import com.appsmith.external.models.ApplicationGitReference; @@ -30,8 +31,9 @@ import static com.appsmith.git.constants.GitDirectories.PAGE_DIRECTORY; public class FileUtilsImplTest { - private FileUtilsImpl fileUtils; + private FileUtilsImpl fileUtils; + private FSGitHandler fsGitHandler; private GitExecutorImpl gitExecutor; private static final String localTestDirectory = "localTestDirectory"; @@ -44,7 +46,12 @@ public void setUp() { gitServiceConfig.setGitRootPath(localTestDirectoryPath.toString()); FileOperations fileOperations = new FileOperationsImpl(null, ObservationHelper.NOOP); fileUtils = new FileUtilsImpl( - gitServiceConfig, gitExecutor, fileOperations, ObservationHelper.NOOP, new ObjectMapper()); + gitServiceConfig, + fsGitHandler, + gitExecutor, + fileOperations, + ObservationHelper.NOOP, + new ObjectMapper()); } @AfterEach diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/OrganizationSpan.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/OrganizationSpan.java new file mode 100644 index 000000000000..a9c025d5794a --- /dev/null +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/OrganizationSpan.java @@ -0,0 +1,5 @@ +package com.appsmith.external.constants.spans; + +import com.appsmith.external.constants.spans.ce.OrganizationSpanCE; + +public class OrganizationSpan extends OrganizationSpanCE {} diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/TenantSpan.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/TenantSpan.java deleted file mode 100644 index 488238e251ec..000000000000 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/TenantSpan.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.appsmith.external.constants.spans; - -import com.appsmith.external.constants.spans.ce.TenantSpanCE; - -public class TenantSpan extends TenantSpanCE {} diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/ConsolidatedApiSpanNamesCE.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/ConsolidatedApiSpanNamesCE.java index 9e2ac07b3ee8..6b8619565624 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/ConsolidatedApiSpanNamesCE.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/ConsolidatedApiSpanNamesCE.java @@ -15,7 +15,7 @@ public class ConsolidatedApiSpanNamesCE { public static final String CONSOLIDATED_API_ROOT_VIEW = CONSOLIDATED_API_PREFIX + VIEW + ROOT; public static final String USER_PROFILE_SPAN = "user_profile"; public static final String FEATURE_FLAG_SPAN = "feature_flag"; - public static final String TENANT_SPAN = "tenant"; + public static final String ORGANIZATION_SPAN = "tenant"; public static final String PRODUCT_ALERT_SPAN = "product_alert"; public static final String APPLICATION_ID_SPAN = "application_id"; public static final String PAGES_SPAN = "pages"; diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/OrganizationSpanCE.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/OrganizationSpanCE.java new file mode 100644 index 000000000000..1ce36010fd97 --- /dev/null +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/OrganizationSpanCE.java @@ -0,0 +1,11 @@ +package com.appsmith.external.constants.spans.ce; + +import static com.appsmith.external.constants.spans.BaseSpan.APPSMITH_SPAN_PREFIX; + +public class OrganizationSpanCE { + public static final String ORGANIZATION_SPAN = APPSMITH_SPAN_PREFIX + "tenant."; + public static final String FETCH_DEFAULT_ORGANIZATION_SPAN = ORGANIZATION_SPAN + "fetch_default_tenant"; + public static final String FETCH_ORGANIZATION_CACHE_POST_DESERIALIZATION_ERROR_SPAN = + ORGANIZATION_SPAN + "fetch_tenant_cache_post_deserialization_error"; + public static final String FETCH_ORGANIZATION_FROM_DB_SPAN = ORGANIZATION_SPAN + "fetch_tenant_from_db"; +} diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/TenantSpanCE.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/TenantSpanCE.java deleted file mode 100644 index 104561730b0a..000000000000 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/spans/ce/TenantSpanCE.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.appsmith.external.constants.spans.ce; - -import static com.appsmith.external.constants.spans.BaseSpan.APPSMITH_SPAN_PREFIX; - -public class TenantSpanCE { - public static final String TENANT_SPAN = APPSMITH_SPAN_PREFIX + "tenant."; - public static final String FETCH_DEFAULT_TENANT_SPAN = TENANT_SPAN + "fetch_default_tenant"; - public static final String FETCH_TENANT_CACHE_POST_DESERIALIZATION_ERROR_SPAN = - TENANT_SPAN + "fetch_tenant_cache_post_deserialization_error"; - public static final String FETCH_TENANT_FROM_DB_SPAN = TENANT_SPAN + "fetch_tenant_from_db"; -} diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/dtos/ExecuteActionDTO.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/dtos/ExecuteActionDTO.java index 1704e0e1cf49..b524a3a2c8a6 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/dtos/ExecuteActionDTO.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/dtos/ExecuteActionDTO.java @@ -20,7 +20,7 @@ public class ExecuteActionDTO { String datasourceId; String workspaceId; String instanceId; - String tenantId; + String organizationId; List params; diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java index 0e47bb43b866..bde30a1ef674 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java @@ -6,7 +6,7 @@ public enum FeatureFlagEnum { TEST_FEATURE_1, TEST_FEATURE_2, TEST_FEATURE_3, - TENANT_TEST_FEATURE, + ORGANIZATION_TEST_FEATURE, // ------------------- End of features for testing -------------------------------------------------------------- // // ------------------- These are actual feature flags meant to be used across the product ----------------------- // diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/exceptions/pluginExceptions/BasePluginErrorMessages.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/exceptions/pluginExceptions/BasePluginErrorMessages.java index e5c0244dfaf3..ff95fe7a66bf 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/exceptions/pluginExceptions/BasePluginErrorMessages.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/exceptions/pluginExceptions/BasePluginErrorMessages.java @@ -21,4 +21,8 @@ public abstract class BasePluginErrorMessages { public static final String INVALID_SSH_KEY_FORMAT_ERROR_MSG = "Invalid SSH key format. Supported formats: OpenSSH, PKCS#8, or RSA PEM."; public static final String SSH_KEY_PARSING_ERROR_MSG = "The provided SSH key could not be parsed."; + public static final String ERROR_INVALID_MULTIPART_DATA = + "Unable to parse content. Expected an array or object of multipart data"; + public static final String ERROR_INVALID_BASE64_FORMAT = + "Invalid BASE64 format. Expected format: data:mimetype;base64,content"; } diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java index 2d43e643b0a1..7aade3725849 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java @@ -39,15 +39,18 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; +import static com.appsmith.external.exceptions.pluginExceptions.BasePluginErrorMessages.ERROR_INVALID_BASE64_FORMAT; +import static com.appsmith.external.exceptions.pluginExceptions.BasePluginErrorMessages.ERROR_INVALID_MULTIPART_DATA; + public class DataUtils { public static String FIELD_API_CONTENT_TYPE = "apiContentType"; @@ -232,8 +235,7 @@ public String parseFormData(List bodyFormData, Boolean encodeParamsTog } catch (IOException e) { e.printStackTrace(); throw new AppsmithPluginException( - AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR, - "Unable to parse content. Expected to receive an array or object of multipart data"); + AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR, ERROR_INVALID_MULTIPART_DATA); } break; case ARRAY: @@ -300,37 +302,108 @@ public String parseFormData(List bodyFormData, Boolean encodeParamsTog private void populateFileTypeBodyBuilder( MultipartBodyBuilder bodyBuilder, Property property, ClientHttpRequest outputMessage) throws IOException { + final String fileValue = (String) property.getValue(); final String key = property.getKey(); - List multipartFormDataDTOs = new ArrayList<>(); + if (fileValue.contains(BASE64_DELIMITER)) { + processBase64Data(fileValue, key, bodyBuilder, outputMessage); + } else { + List multipartFormDataDTOs = parseMultipartData(fileValue); + + for (MultipartFormDataDTO dto : multipartFormDataDTOs) { + String dataString = String.valueOf(dto.getData()); + if (dataString.contains(BASE64_DELIMITER)) { + processBase64Data(dataString, key, bodyBuilder, outputMessage, dto.getName(), dto.getType()); + } else { + processRegularData(dataString, key, bodyBuilder, outputMessage, dto.getName(), dto.getType()); + } + } + } + } + + // Process BASE64-encoded content + private void processBase64Data( + String fileValue, String key, MultipartBodyBuilder bodyBuilder, ClientHttpRequest outputMessage) { + processBase64Data(fileValue, key, bodyBuilder, outputMessage, "file", "application/octet-stream"); + } + + // Overloaded method with custom filename & MIME type + private void processBase64Data( + String fileValue, + String key, + MultipartBodyBuilder bodyBuilder, + ClientHttpRequest outputMessage, + String filename, + String defaultMimeType) { + String[] parts = fileValue.split(BASE64_DELIMITER, 2); + if (parts.length != 2) { + throw new AppsmithPluginException( + AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR, ERROR_INVALID_BASE64_FORMAT); + } + + String metadataPart = parts[0]; + String base64Content = parts[1]; + String mimeType = extractMimeType(metadataPart, defaultMimeType); + byte[] decodedBytes = Base64.getMimeDecoder().decode(base64Content); + + addPartToBody(bodyBuilder, key, decodedBytes, outputMessage, filename, mimeType); + } + + // Process regular string data + private void processRegularData( + String data, + String key, + MultipartBodyBuilder bodyBuilder, + ClientHttpRequest outputMessage, + String filename, + String mimeType) { + byte[] bytes = data.getBytes(StandardCharsets.ISO_8859_1); + addPartToBody(bodyBuilder, key, bytes, outputMessage, filename, mimeType); + } + + // Extract MIME type from metadata string + // The metadataPart typically follows this format: "data:mimetype;base64" + // Example values: + // - "data:image/png;base64" -> Extracted MIME type: "image/png" + // - "data:application/pdf;base64" -> Extracted MIME type: "application/pdf" + // - "data:text/plain;" (without base64) -> Extracted MIME type: "text/plain" + // If the format is incorrect or missing, it falls back to the default MIME type. + private String extractMimeType(String metadataPart, String defaultMimeType) { + if (metadataPart.startsWith("data:")) { + int endIndex = metadataPart.indexOf(';'); + if (endIndex > 5) { + return metadataPart.substring(5, endIndex); + } else { + return metadataPart.substring(5); + } + } + return defaultMimeType; + } + + // Add a part to the MultipartBodyBuilder + private void addPartToBody( + MultipartBodyBuilder bodyBuilder, + String key, + byte[] bytes, + ClientHttpRequest outputMessage, + String filename, + String mimeType) { + Flux data = DataBufferUtils.readInputStream( + () -> new ByteArrayInputStream(bytes), outputMessage.bufferFactory(), 4096); + bodyBuilder.asyncPart(key, data, DataBuffer.class).filename(filename).contentType(MediaType.valueOf(mimeType)); + } + + // Parse JSON multipart data + private List parseMultipartData(String fileValue) throws IOException { if (fileValue.startsWith("{")) { - // Check whether the JSON string is an object - final MultipartFormDataDTO multipartFormDataDTO = - objectMapper.readValue(fileValue, MultipartFormDataDTO.class); - multipartFormDataDTOs.add(multipartFormDataDTO); + return Collections.singletonList(objectMapper.readValue(fileValue, MultipartFormDataDTO.class)); } else if (fileValue.startsWith("[")) { - // Check whether the JSON string is an array - multipartFormDataDTOs = Arrays.asList(objectMapper.readValue(fileValue, MultipartFormDataDTO[].class)); + return Arrays.asList(objectMapper.readValue(fileValue, MultipartFormDataDTO[].class)); } else { throw new AppsmithPluginException( - AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR, - "Unable to parse content. Expected to receive an array or object of multipart data"); + AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR, ERROR_INVALID_MULTIPART_DATA); } - - multipartFormDataDTOs.forEach(multipartFormDataDTO -> { - final MultipartFormDataDTO finalMultipartFormDataDTO = multipartFormDataDTO; - Flux data = DataBufferUtils.readInputStream( - () -> new ByteArrayInputStream( - String.valueOf(finalMultipartFormDataDTO.getData()).getBytes(StandardCharsets.ISO_8859_1)), - outputMessage.bufferFactory(), - 4096); - - bodyBuilder - .asyncPart(key, data, DataBuffer.class) - .filename(multipartFormDataDTO.getName()) - .contentType(MediaType.valueOf(multipartFormDataDTO.getType())); - }); } /** diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java index a038402c7cbe..3a0e7898f685 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java @@ -89,6 +89,9 @@ public class DatasourceStorage extends GitSyncedDomain { @Transient Boolean isMock; + @Transient + Map metadata; + public DatasourceStorage( String datasourceId, String environmentId, diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/TriggerRequestDTO.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/TriggerRequestDTO.java index 6c1aae7faeba..01284535afe7 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/TriggerRequestDTO.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/TriggerRequestDTO.java @@ -37,7 +37,7 @@ public class TriggerRequestDTO { String datasourceId; String actionId; String instanceId; - String tenantId; + String organizationId; // this param is expected to be sent by the client if needed String workspaceId; diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java index a95a7c2988ac..5f9cdb89d1b3 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/PluginExecutor.java @@ -185,6 +185,13 @@ default Mono preDeleteHook(DatasourceStorage datasourceStorag return Mono.just(datasourceStorage); } + /** + * This function is being called as a hook after saving a datasource. + */ + default Mono postSaveHook(DatasourceStorage datasourceStorage) { + return Mono.just(datasourceStorage); + } + /** * This function fetches the structure of the tables/collections in the datasource. It's used to make query creation * easier for the user. @@ -248,12 +255,10 @@ default Mono executeParameterizedWithMetrics( } // TODO: Following methods of executeParameterizedWithFlags, executeParameterizedWithMetricsAndFlags, - // triggerWithFlags are - // added - // to support feature flags in the plugin modules. Current implementation of featureFlagService is only available in - // server module - // and not available in any of the plugin modules due to dependencies on SessionUserService, TenantService etc. - // Hence, these methods are added to support feature flags in the plugin modules. + // triggerWithFlags are added to support feature flags in the plugin modules. Current implementation of + // featureFlagService is only available in server module and not available in any of the plugin modules due to + // dependencies on SessionUserService, OrganizationService etc. Hence, these methods are added to support feature + // flags in the plugin modules. // Ideal solution would be to move featureFlagService and its dependencies to the shared interface module // But this is a bigger change and will be done in future. Current change of passing flags was done to resolve // release blocker diff --git a/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/constants/AppsmithAiConstants.java b/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/constants/AppsmithAiConstants.java index 384d297f0624..9ca3a1d8007d 100644 --- a/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/constants/AppsmithAiConstants.java +++ b/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/constants/AppsmithAiConstants.java @@ -32,7 +32,7 @@ public class AppsmithAiConstants { public static final String ACTION_ID = "actionId"; public static final String WORKSPACE_ID = "workspaceId"; public static final String INSTANCE_ID = "instanceId"; - public static final String TENANT_ID = "tenantId"; + public static final String ORGANIZATION_ID = "tenantId"; public static final String SOURCE_DETAILS = "sourceDetail"; public static final String PERIOD_DELIMITER = "."; diff --git a/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/dtos/SourceDetails.java b/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/dtos/SourceDetails.java index 34fdbc2dc6cb..75b554fa020c 100644 --- a/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/dtos/SourceDetails.java +++ b/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/dtos/SourceDetails.java @@ -9,14 +9,14 @@ public class SourceDetails { String workspaceId; String datasourceId; String instanceId; - String tenantId; + String organizationId; public static SourceDetails createSourceDetails(ExecuteActionDTO executeActionDTO) { SourceDetails sourceDetails = new SourceDetails(); sourceDetails.setWorkspaceId(executeActionDTO.getWorkspaceId()); sourceDetails.setDatasourceId(executeActionDTO.getDatasourceId()); sourceDetails.setInstanceId(executeActionDTO.getInstanceId()); - sourceDetails.setTenantId(executeActionDTO.getTenantId()); + sourceDetails.setOrganizationId(executeActionDTO.getOrganizationId()); return sourceDetails; } @@ -25,7 +25,7 @@ public static SourceDetails createSourceDetails(TriggerRequestDTO triggerRequest sourceDetails.setWorkspaceId(triggerRequestDTO.getWorkspaceId()); sourceDetails.setDatasourceId(triggerRequestDTO.getDatasourceId()); sourceDetails.setInstanceId(triggerRequestDTO.getInstanceId()); - sourceDetails.setTenantId(triggerRequestDTO.getTenantId()); + sourceDetails.setOrganizationId(triggerRequestDTO.getOrganizationId()); return sourceDetails; } } diff --git a/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/utils/HeadersUtil.java b/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/utils/HeadersUtil.java index 9cc8562a0309..965e11a53fe2 100644 --- a/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/utils/HeadersUtil.java +++ b/app/server/appsmith-plugins/appsmithAiPlugin/src/main/java/com/external/plugins/utils/HeadersUtil.java @@ -6,7 +6,7 @@ import static com.external.plugins.constants.AppsmithAiConstants.ACTION_ID; import static com.external.plugins.constants.AppsmithAiConstants.DATASOURCE_ID; import static com.external.plugins.constants.AppsmithAiConstants.INSTANCE_ID; -import static com.external.plugins.constants.AppsmithAiConstants.TENANT_ID; +import static com.external.plugins.constants.AppsmithAiConstants.ORGANIZATION_ID; import static com.external.plugins.constants.AppsmithAiConstants.WORKSPACE_ID; public class HeadersUtil { @@ -46,9 +46,9 @@ public static String createSourceDetailsHeader(SourceDetails sourceDetails) { + COLON + sourceDetails.getWorkspaceId() + SEMI_COLON - + TENANT_ID + + ORGANIZATION_ID + COLON - + sourceDetails.getTenantId() + + sourceDetails.getOrganizationId() + SEMI_COLON + INSTANCE_ID + COLON diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java index 1d718b9f17f1..9ee3717cc9d0 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AclPermission.java @@ -7,8 +7,8 @@ import com.appsmith.server.domains.Config; import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.PermissionGroup; -import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.Theme; import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; @@ -120,8 +120,10 @@ public enum AclPermission { @Deprecated READ_PERMISSION_GROUPS("read:permissionGroups", PermissionGroup.class), - // Manage tenant permissions - MANAGE_TENANT("manage:tenants", Tenant.class), + // Manage organization permissions + MANAGE_ORGANIZATION("manage:organization", Organization.class), + @Deprecated(forRemoval = true, since = "v1.62") + MANAGE_TENANT("manage:tenant", Organization.class), CONNECT_TO_GIT("connectToGit:applications", Application.class), MANAGE_PROTECTED_BRANCHES("manageProtectedBranches:applications", Application.class), diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java index 2f71537d7de4..85f0a91176be 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/acl/AppsmithRole.java @@ -5,7 +5,7 @@ import java.util.Set; import static com.appsmith.server.acl.AclPermission.DELETE_WORKSPACES; -import static com.appsmith.server.acl.AclPermission.MANAGE_TENANT; +import static com.appsmith.server.acl.AclPermission.MANAGE_ORGANIZATION; import static com.appsmith.server.acl.AclPermission.MANAGE_WORKSPACES; import static com.appsmith.server.acl.AclPermission.READ_WORKSPACES; import static com.appsmith.server.acl.AclPermission.WORKSPACE_CREATE_APPLICATION; @@ -62,7 +62,7 @@ public enum AppsmithRole { WORKSPACE_READ_APPLICATIONS, WORKSPACE_INVITE_USERS, WORKSPACE_EXECUTE_DATASOURCES)), - TENANT_ADMIN("", "", Set.of(MANAGE_TENANT)), + TENANT_ADMIN("", "", Set.of(MANAGE_ORGANIZATION)), ; private Set permissions; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java index 2216f66e8ce4..e0377b652b23 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java @@ -65,7 +65,7 @@ private Object invokeMethod(ProceedingJoinPoint joinPoint, FeatureFlagged annota return featureFlagMono.flatMapMany(isSupported -> (Flux) invokeMethod(isSupported, joinPoint, method)); } // For non-reactive methods with feature flagging annotation we will be using the in memory feature flag cache - // which is getting updated whenever the tenant feature flags are updated. + // which is getting updated whenever the organization feature flags are updated. return invokeMethod(isFeatureFlagEnabled(flagName), joinPoint, method); } @@ -108,7 +108,7 @@ AppsmithException getInvalidAnnotationUsageException(Method method, String error } boolean isFeatureFlagEnabled(FeatureFlagEnum flagName) { - CachedFeatures cachedFeatures = featureFlagService.getCachedTenantFeatureFlags(); + CachedFeatures cachedFeatures = featureFlagService.getCachedOrganizationFeatureFlags(); return cachedFeatures != null && !CollectionUtils.isNullOrEmpty(cachedFeatures.getFeatures()) && Boolean.TRUE.equals(cachedFeatures.getFeatures().get(flagName.name())); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java index 66467580e46a..4d538b6e552e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java @@ -8,8 +8,8 @@ import com.appsmith.server.repositories.WorkspaceRepository; import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.ApplicationPageService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import com.appsmith.server.services.WorkspaceService; @@ -32,7 +32,7 @@ public AuthenticationSuccessHandler( ApplicationPageService applicationPageService, WorkspacePermission workspacePermission, RateLimitService rateLimitService, - TenantService tenantService, + OrganizationService organizationService, UserService userService, WorkspaceServiceHelper workspaceServiceHelper) { super( @@ -46,7 +46,7 @@ public AuthenticationSuccessHandler( applicationPageService, workspacePermission, rateLimitService, - tenantService, + organizationService, userService, workspaceServiceHelper); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java index 1b4054ddb248..c9a02b286a55 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java @@ -17,8 +17,8 @@ import com.appsmith.server.repositories.WorkspaceRepository; import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.ApplicationPageService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import com.appsmith.server.services.WorkspaceService; @@ -65,14 +65,14 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce private final ApplicationPageService applicationPageService; private final WorkspacePermission workspacePermission; private final RateLimitService rateLimitService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final UserService userService; private final WorkspaceServiceHelper workspaceServiceHelper; private Mono isVerificationRequired(String userEmail, String method) { - Mono emailVerificationEnabledMono = tenantService - .getTenantConfiguration() - .map(tenant -> tenant.getTenantConfiguration().isEmailVerificationEnabled()) + Mono emailVerificationEnabledMono = organizationService + .getOrganizationConfiguration() + .map(organization -> organization.getOrganizationConfiguration().isEmailVerificationEnabled()) .cache(); Mono userMono = userRepository.findByEmail(userEmail).cache(); @@ -80,7 +80,7 @@ private Mono isVerificationRequired(String userEmail, String method) { if ("signup".equals(method)) { verificationRequiredMono = emailVerificationEnabledMono.flatMap(emailVerificationEnabled -> { - // email verification is not enabled at the tenant, so verification not required + // email verification is not enabled at the org, so verification not required if (!TRUE.equals(emailVerificationEnabled)) { return userMono.flatMap(user -> { user.setEmailVerificationRequired(FALSE); @@ -101,12 +101,12 @@ private Mono isVerificationRequired(String userEmail, String method) { return Mono.just(FALSE); } else { return emailVerificationEnabledMono.flatMap(emailVerificationEnabled -> { - // email verification not enabled at the tenant + // email verification not enabled at the org if (!TRUE.equals(emailVerificationEnabled)) { user.setEmailVerificationRequired(FALSE); return userRepository.save(user).then(Mono.just(FALSE)); } else { - // scenario when at the time of signup, the email verification was disabled at the tenant + // scenario when at the time of signup, the email verification was disabled at the org // but later on turned on, now when this user logs in, it will not be prompted to verify // as the configuration at time of signup is considered for any user. // for old users, the login works as expected, without the need to verify diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/LogoutSuccessHandlerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/LogoutSuccessHandlerCE.java index 201e5fea333c..e18d4f34cc0b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/LogoutSuccessHandlerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/LogoutSuccessHandlerCE.java @@ -45,7 +45,7 @@ public Mono onLogoutSuccess(WebFilterExchange webFilterExchange, Authentic ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.OK); response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); - ResponseDTO responseBody = new ResponseDTO<>(HttpStatus.OK.value(), true, null); + ResponseDTO responseBody = new ResponseDTO<>(HttpStatus.OK, true); String responseStr; try { responseStr = objectMapper.writeValueAsString(responseBody); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java index 879780c0bb71..261286df2b33 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java @@ -61,17 +61,18 @@ public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { // Prefill the server cache with anonymous user permission group ids. .then(cacheableRepositoryHelper.preFillAnonymousUserPermissionGroupIdsCache()) // Add cold publisher as we have dependency on the instance registration - // TODO Update implementation to fetch license status for all the tenants once multi-tenancy is + // TODO Update implementation to fetch license status for all the organizations once multi-tenancy is // introduced .then(Mono.defer(instanceConfigHelper::isLicenseValid) - // Ensure that the tenant feature flags are refreshed with the latest values after completing + // Ensure that the organization feature flags are refreshed with the latest values after + // completing // the // license verification process. .flatMap(isValid -> { log.debug( "License verification completed with status: {}", TRUE.equals(isValid) ? "valid" : "invalid"); - return instanceConfigHelper.updateCacheForTenantFeatureFlags(); + return instanceConfigHelper.updateCacheForOrganizationFeatureFlags(); })); try { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/NoTagsMeterFilter.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/NoTagsMeterFilter.java index 95b1f30af77a..d2011eb3199d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/NoTagsMeterFilter.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/NoTagsMeterFilter.java @@ -4,13 +4,27 @@ import io.micrometer.core.instrument.Tags; import io.micrometer.core.instrument.config.MeterFilter; +import java.util.List; + public class NoTagsMeterFilter implements MeterFilter { + private static final List seriesExceptionList = List.of( + "appsmith.total.plugin.execution", "appsmith.total.server.execution", "appsmith.get.datasource.context"); + @Override public Meter.Id map(Meter.Id id) { // Remove all tags from the metric - if (id.getName().startsWith("appsmith")) { + if (id.getName().startsWith("appsmith") && !startsWithPrefix(id.getName())) { return id.replaceTags(Tags.empty()); } return id; } + + private boolean startsWithPrefix(String metricName) { + for (String prefix : seriesExceptionList) { + if (metricName.startsWith(prefix)) { + return true; + } + } + return false; + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/OrganizationConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/OrganizationConfig.java new file mode 100644 index 000000000000..49844825d2b5 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/OrganizationConfig.java @@ -0,0 +1,47 @@ +package com.appsmith.server.configurations; + +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.helpers.CollectionUtils; +import com.appsmith.server.repositories.CacheableRepositoryHelper; +import com.appsmith.server.repositories.OrganizationRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Configuration; +import reactor.core.publisher.Mono; + +import static com.appsmith.external.models.BaseDomain.policySetToMap; + +@Configuration +@RequiredArgsConstructor +@Slf4j +public class OrganizationConfig implements ApplicationListener { + + private final OrganizationRepository organizationRepository; + private final CacheableRepositoryHelper cacheableRepositoryHelper; + + // Method to cleanup the cache and update the default organization policies if the policyMap is empty. This will + // make sure + // cache will be updated if we update the organization via startup DB migrations. + // As we have mocked the OrganizationService in the tests, we had to manually evict the cache and save the object to + // DB + private Mono cleanupAndUpdateRefreshDefaultOrganizationPolicies() { + log.debug("Cleaning up and updating default organization policies on server startup"); + return organizationRepository.findBySlug(FieldName.DEFAULT).flatMap(organization -> { + if (CollectionUtils.isNullOrEmpty(organization.getPolicyMap())) { + organization.setPolicyMap(policySetToMap(organization.getPolicies())); + return cacheableRepositoryHelper + .evictCachedOrganization(organization.getId()) + .then(organizationRepository.save(organization)); + } + return Mono.just(organization); + }); + } + + @Override + public void onApplicationEvent(ApplicationStartedEvent event) { + cleanupAndUpdateRefreshDefaultOrganizationPolicies().block(); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java index f44711f4c82a..ecf53ac70d16 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java @@ -67,9 +67,9 @@ import static com.appsmith.server.constants.Url.APPLICATION_URL; import static com.appsmith.server.constants.Url.ASSET_URL; import static com.appsmith.server.constants.Url.CUSTOM_JS_LIB_URL; +import static com.appsmith.server.constants.Url.ORGANIZATION_URL; import static com.appsmith.server.constants.Url.PAGE_URL; import static com.appsmith.server.constants.Url.PRODUCT_ALERT; -import static com.appsmith.server.constants.Url.TENANT_URL; import static com.appsmith.server.constants.Url.THEME_URL; import static com.appsmith.server.constants.Url.USAGE_PULSE_URL; import static com.appsmith.server.constants.Url.USER_URL; @@ -213,7 +213,7 @@ public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, APPLICATION_URL + "/**"), ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, THEME_URL + "/**"), ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, ACTION_URL + "/execute"), - ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, TENANT_URL + "/current"), + ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, ORGANIZATION_URL + "/current"), ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, USAGE_PULSE_URL), ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, CUSTOM_JS_LIB_URL + "/*/view"), ServerWebExchangeMatchers.pathMatchers( diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/TenantConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/TenantConfig.java deleted file mode 100644 index 544430ca03ca..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/TenantConfig.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.appsmith.server.configurations; - -import com.appsmith.server.constants.FieldName; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.helpers.CollectionUtils; -import com.appsmith.server.repositories.CacheableRepositoryHelper; -import com.appsmith.server.repositories.TenantRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.event.ApplicationStartedEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.context.annotation.Configuration; -import reactor.core.publisher.Mono; - -import static com.appsmith.external.models.BaseDomain.policySetToMap; - -@Configuration -@RequiredArgsConstructor -@Slf4j -public class TenantConfig implements ApplicationListener { - - private final TenantRepository tenantRepository; - private final CacheableRepositoryHelper cachableRepositoryHelper; - - // Method to cleanup the cache and update the default tenant policies if the policyMap is empty. This will make sure - // cache will be updated if we update the tenant via startup DB migrations. - // As we have mocked the TenantService in the tests, we had to manually evict the cache and save the object to DB - private Mono cleanupAndUpdateRefreshDefaultTenantPolicies() { - log.debug("Cleaning up and updating default tenant policies on server startup"); - return tenantRepository.findBySlug(FieldName.DEFAULT).flatMap(tenant -> { - if (CollectionUtils.isNullOrEmpty(tenant.getPolicyMap())) { - tenant.setPolicyMap(policySetToMap(tenant.getPolicies())); - return cachableRepositoryHelper - .evictCachedTenant(tenant.getId()) - .then(tenantRepository.save(tenant)); - } - return Mono.just(tenant); - }); - } - - @Override - public void onApplicationEvent(ApplicationStartedEvent event) { - cleanupAndUpdateRefreshDefaultTenantPolicies().block(); - } -} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCECompatibleImpl.java index 90fbc54eb4cc..1f78a25c43d6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCECompatibleImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCECompatibleImpl.java @@ -1,12 +1,12 @@ package com.appsmith.server.configurations.git; import com.appsmith.external.configurations.git.GitConfigCECompatible; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import org.springframework.stereotype.Component; @Component public class GitConfigCECompatibleImpl extends GitConfigCEImpl implements GitConfigCECompatible { - public GitConfigCECompatibleImpl(TenantService tenantService) { - super(tenantService); + public GitConfigCECompatibleImpl(OrganizationService organizationService) { + super(organizationService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCEImpl.java index b75010ad32d0..441cc3a7dfcf 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigCEImpl.java @@ -1,7 +1,7 @@ package com.appsmith.server.configurations.git; import com.appsmith.external.configurations.git.GitConfigCE; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; @@ -10,13 +10,13 @@ @Component public class GitConfigCEImpl implements GitConfigCE { - private final TenantService tenantService; + private final OrganizationService organizationService; @Override public Mono getIsAtomicPushAllowed() { - return tenantService - .getTenantConfiguration() - .map(tenant -> tenant.getTenantConfiguration().getIsAtomicPushAllowed()) + return organizationService + .getOrganizationConfiguration() + .map(organization -> organization.getOrganizationConfiguration().getIsAtomicPushAllowed()) .switchIfEmpty(Mono.just(false)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigImpl.java index 3cef3e9c08c4..1bf8d6d51525 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/git/GitConfigImpl.java @@ -1,12 +1,12 @@ package com.appsmith.server.configurations.git; import com.appsmith.external.configurations.git.GitConfig; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import org.springframework.stereotype.Component; @Component public class GitConfigImpl extends GitConfigCECompatibleImpl implements GitConfig { - public GitConfigImpl(TenantService tenantService) { - super(tenantService); + public GitConfigImpl(OrganizationService organizationService) { + super(organizationService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java index 2ffdc1ba5c7f..2b53895370cc 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/FieldNameCE.java @@ -183,7 +183,7 @@ public class FieldNameCE { public static final String ENVIRONMENT = "environment"; public static final String UNUSED_ENVIRONMENT_ID = "unused_env"; - public static final String TENANT = "tenant"; + public static final String ORGANIZATION = "organization"; public static final String SUFFIX_USER_MANAGEMENT_ROLE = " User Management"; @@ -197,6 +197,7 @@ public class FieldNameCE { public static final String REMOTE_PLUGINS = "remotePlugins"; public static final String INSTANCE_ID = "instanceId"; + public static final String TENANT_ID = "tenantId"; public static final String IP_ADDRESS = "ipAddress"; public static final String VERSION = "version"; public static final String PUBLISHED = "published"; @@ -204,5 +205,6 @@ public class FieldNameCE { public static final String ARTIFACT_CONTEXT = "artifactContext"; public static final String ARTIFACT_ID = "artifactId"; public static final String BODY = "body"; + public static final String ORGANIZATION_ID = "organizationId"; public static final String NONE = "none"; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/UrlCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/UrlCE.java index c070dbeabc2e..6e1780ba6f2f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/UrlCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/ce/UrlCE.java @@ -27,7 +27,7 @@ public class UrlCE { public static final String THEME_URL = BASE_URL + VERSION + "/themes"; public static final String APP_TEMPLATE_URL = BASE_URL + VERSION + "/app-templates"; public static final String USAGE_PULSE_URL = BASE_URL + VERSION + "/usage-pulse"; - public static final String TENANT_URL = BASE_URL + VERSION + "/tenants"; + public static final String ORGANIZATION_URL = BASE_URL + VERSION + "/tenants"; public static final String CUSTOM_JS_LIB_URL = BASE_URL + VERSION + "/libraries"; public static final String PRODUCT_ALERT = BASE_URL + VERSION + "/product-alert"; public static final String SEARCH_ENTITY_URL = BASE_URL + VERSION + "/search-entities"; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ConsolidatedAPIController.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ConsolidatedAPIController.java index 4dc87ba917f2..f39a8299c8ec 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ConsolidatedAPIController.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ConsolidatedAPIController.java @@ -70,8 +70,7 @@ public Mono> getAllDataForFirstPageLoadF return consolidatedAPIService .getConsolidatedInfoForPageLoad(basePageId, baseApplicationId, refType, refName, ApplicationMode.EDIT) - .map(consolidatedAPIResponseDTO -> - new ResponseDTO<>(HttpStatus.OK.value(), consolidatedAPIResponseDTO, null)) + .map(consolidatedAPIResponseDTO -> new ResponseDTO<>(HttpStatus.OK, consolidatedAPIResponseDTO)) .tag("pageId", Objects.toString(basePageId)) .tag("applicationId", Objects.toString(baseApplicationId)) .tag("refType", Objects.toString(refType)) @@ -116,7 +115,7 @@ public Mono>> getAllDataF // if defaultPageId and applicationId are both null, then don't compute ETag if (isBlank(responseHash)) { ResponseDTO responseDTO = - new ResponseDTO<>(HttpStatus.OK.value(), consolidatedAPIResponseDTO, null); + new ResponseDTO<>(HttpStatus.OK, consolidatedAPIResponseDTO); return new ResponseEntity<>(responseDTO, HttpStatus.OK); } @@ -126,12 +125,12 @@ public Mono>> getAllDataF if (ifNoneMatch != null && ifNoneMatch.equals(responseHash)) { ResponseDTO responseDTO = - new ResponseDTO<>(HttpStatus.NOT_MODIFIED.value(), null, null); + new ResponseDTO<>(HttpStatus.NOT_MODIFIED, null); return new ResponseEntity<>(responseDTO, headers, HttpStatus.NOT_MODIFIED); } ResponseDTO responseDTO = - new ResponseDTO<>(HttpStatus.OK.value(), consolidatedAPIResponseDTO, null); + new ResponseDTO<>(HttpStatus.OK, consolidatedAPIResponseDTO); return new ResponseEntity<>(responseDTO, headers, HttpStatus.OK); }) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/TenantController.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/OrganizationController.java similarity index 50% rename from app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/TenantController.java rename to app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/OrganizationController.java index 15a914eeac6f..45de4b18e74a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/TenantController.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/OrganizationController.java @@ -1,18 +1,18 @@ package com.appsmith.server.controllers; import com.appsmith.server.constants.Url; -import com.appsmith.server.controllers.ce.TenantControllerCE; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.controllers.ce.OrganizationControllerCE; +import com.appsmith.server.services.OrganizationService; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j -@RequestMapping(Url.TENANT_URL) -public class TenantController extends TenantControllerCE { +@RequestMapping(Url.ORGANIZATION_URL) +public class OrganizationController extends OrganizationControllerCE { - public TenantController(TenantService service) { + public OrganizationController(OrganizationService service) { super(service); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionCollectionControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionCollectionControllerCE.java index 633dbf2fe4f9..d5d2658fa46e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionCollectionControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionCollectionControllerCE.java @@ -55,7 +55,7 @@ public Mono> create(@Valid @RequestBody ActionC log.debug("Going to create action collection {}", resource.getClass().getName()); return layoutCollectionService .createCollection(resource) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -66,7 +66,7 @@ public Mono>> getAllUnpublishedActionColle return actionCollectionService .getPopulatedActionCollectionsByViewMode(params, false) .collectList() - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } @JsonView(Views.Public.class) @@ -79,7 +79,7 @@ public Mono> moveActionCollection( actionCollectionMoveDTO.getDestinationPageId()); return layoutCollectionService .moveCollection(actionCollectionMoveDTO) - .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK.value(), actionCollection, null)); + .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK, actionCollection)); } @JsonView(Views.Public.class) @@ -89,7 +89,7 @@ public Mono> refactorActionCollectionName( refactorEntityNameDTO.setEntityType(EntityType.JS_OBJECT); return refactoringService .refactorEntityName(refactorEntityNameDTO) - .map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.OK, created)); } @JsonView(Views.Public.class) @@ -100,7 +100,7 @@ public Mono>> getAllPublishedActionCol return actionCollectionService .getActionCollectionsForViewMode(applicationId, null) .collectList() - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } @JsonView(Views.Public.class) @@ -110,7 +110,7 @@ public Mono> updateActionCollection( log.debug("Going to update action collection with id: {}", id); return layoutCollectionService .updateUnpublishedActionCollection(id, resource) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -120,7 +120,7 @@ public Mono> updateActionCollectionBody( log.debug("Going to update action collection body with id: {}", id); return layoutCollectionService .updateUnpublishedActionCollectionBody(id, resource) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -134,7 +134,7 @@ public Mono> refactorActionCollection( refactorEntityNameDTO.setEntityType(EntityType.JS_ACTION); return refactoringService .refactorEntityName(refactorEntityNameDTO) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -143,6 +143,6 @@ public Mono> deleteActionCollection(@PathVariab log.debug("Going to delete unpublished action collection with id: {}", id); return actionCollectionService .deleteUnpublishedActionCollection(id) - .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null)); + .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK, deletedResource)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java index 62f437a4372a..39498b77a645 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java @@ -58,7 +58,7 @@ public Mono> createAction( log.debug("Going to create resource {}", resource.getClass().getName()); return layoutActionService .createSingleAction(resource) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -69,7 +69,7 @@ public Mono> updateAction( log.debug("Going to update resource with branchedActionId: {}", branchedActionId); return layoutActionService .updateNewActionByBranchedId(branchedActionId, resource) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -82,7 +82,7 @@ public Mono> executeAction( return actionExecutionSolution .executeAction( partFlux, environmentId, serverWebExchange.getRequest().getHeaders(), Boolean.FALSE) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -93,9 +93,7 @@ public Mono> moveAction(@RequestBody @Valid ActionMoveDTO actionMoveDTO.getAction().getName(), actionMoveDTO.getAction().getPageId(), actionMoveDTO.getDestinationPageId()); - return layoutActionService - .moveAction(actionMoveDTO) - .map(action -> new ResponseDTO<>(HttpStatus.OK.value(), action, null)); + return layoutActionService.moveAction(actionMoveDTO).map(action -> new ResponseDTO<>(HttpStatus.OK, action)); } @JsonView(Views.Public.class) @@ -104,7 +102,7 @@ public Mono> refactorActionName(@RequestBody RefactorEnti refactorEntityNameDTO.setEntityType(EntityType.ACTION); return refactoringService .refactorEntityName(refactorEntityNameDTO) - .map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.OK, created)); } @JsonView(Views.Public.class) @@ -114,7 +112,7 @@ public Mono>> getActionsForViewMode( return newActionService .getActionsForViewMode(branchedApplicationId) .collectList() - .map(actions -> new ResponseDTO<>(HttpStatus.OK.value(), actions, null)); + .map(actions -> new ResponseDTO<>(HttpStatus.OK, actions)); } @JsonView(Views.Public.class) @@ -124,7 +122,7 @@ public Mono> setExecuteOnLoad( log.debug("Going to set execute on load for action id {} to {}", branchedActionId, flag); return layoutActionService .setExecuteOnLoad(branchedActionId, flag) - .map(action -> new ResponseDTO<>(HttpStatus.OK.value(), action, null)); + .map(action -> new ResponseDTO<>(HttpStatus.OK, action)); } @JsonView(Views.Public.class) @@ -134,7 +132,7 @@ public Mono> deleteAction( log.debug("Going to delete unpublished action with id: {}, branchName: {}", id, branchName); return layoutActionService .deleteUnpublishedAction(id) - .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null)); + .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK, deletedResource)); } /** @@ -154,6 +152,6 @@ public Mono>> getAllUnpublishedActions( return newActionService .getUnpublishedActionsExceptJs(params) .collectList() - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } } 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 f1512a8866f9..11c32aa490b3 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 @@ -83,7 +83,7 @@ public Mono> create(@Valid @RequestBody ApplicationCrea log.debug("Going to create application in workspace {}", resource.workspaceId()); return applicationPageService .createApplication(resource.toApplication()) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -93,7 +93,7 @@ public Mono> publish( @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { return applicationPageService .publish(branchedApplicationId, true) - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null)); + .thenReturn(new ResponseDTO<>(HttpStatus.OK, true)); } @JsonView(Views.Public.class) @@ -102,7 +102,7 @@ public Mono> makeDefault( @PathVariable String branchedApplicationId, @PathVariable String branchedPageId) { return applicationPageService .makePageDefault(branchedApplicationId, branchedPageId) - .map(updatedApplication -> new ResponseDTO<>(HttpStatus.OK.value(), updatedApplication, null)); + .map(updatedApplication -> new ResponseDTO<>(HttpStatus.OK, updatedApplication)); } @JsonView(Views.Public.class) @@ -113,7 +113,7 @@ public Mono> reorderPage( @RequestParam Integer order) { return applicationPageService .reorderPage(branchedApplicationId, branchedPageId, order) - .map(updatedApplication -> new ResponseDTO<>(HttpStatus.OK.value(), updatedApplication, null)); + .map(updatedApplication -> new ResponseDTO<>(HttpStatus.OK, updatedApplication)); } @JsonView(Views.Public.class) @@ -122,7 +122,7 @@ public Mono> delete(@PathVariable String branchedApplic log.debug("Going to delete application with branchedApplicationId: {}", branchedApplicationId); return applicationPageService .deleteApplication(branchedApplicationId) - .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null)); + .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK, deletedResource)); } @JsonView(Views.Public.class) @@ -132,16 +132,14 @@ public Mono>> findByWorkspaceIdAndRecentlyUsedOrde log.debug("Going to get all applications by workspace id {}", workspaceId); return service.findByWorkspaceIdAndBaseApplicationsInRecentlyUsedOrder(workspaceId) .collectList() - .map(applications -> new ResponseDTO<>(HttpStatus.OK.value(), applications, null)); + .map(applications -> new ResponseDTO<>(HttpStatus.OK, applications)); } @JsonView(Views.Public.class) @GetMapping(Url.RELEASE_ITEMS) public Mono> getReleaseItemsInformation() { log.debug("Going to get version release items"); - return userReleaseNotes - .getReleaseItems() - .map(applications -> new ResponseDTO<>(HttpStatus.OK.value(), applications, null)); + return userReleaseNotes.getReleaseItems().map(applications -> new ResponseDTO<>(HttpStatus.OK, applications)); } @JsonView(Views.Public.class) @@ -154,7 +152,7 @@ public Mono> shareApplication( applicationAccessDTO.getPublicAccess()); return service.changeViewAccessForAllBranchesByBranchedApplicationId( branchedApplicationId, applicationAccessDTO) - .map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null)); + .map(application -> new ResponseDTO<>(HttpStatus.OK, application)); } @JsonView(Views.Public.class) @@ -162,14 +160,14 @@ public Mono> shareApplication( public Mono> cloneApplication(@PathVariable String branchedApplicationId) { return applicationPageService .cloneApplication(branchedApplicationId) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @GetMapping("/view/{branchedApplicationId}") public Mono> getApplicationInViewMode(@PathVariable String branchedApplicationId) { return service.getApplicationInViewMode(branchedApplicationId) - .map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null)); + .map(application -> new ResponseDTO<>(HttpStatus.OK, application)); } @JsonView(Views.Public.class) @@ -178,7 +176,7 @@ public Mono> forkApplication( @PathVariable String branchedApplicationId, @PathVariable String workspaceId) { return applicationForkingService .forkApplicationToWorkspace(branchedApplicationId, workspaceId) - .map(fetchedResource -> new ResponseDTO<>(HttpStatus.OK.value(), fetchedResource, null)); + .map(fetchedResource -> new ResponseDTO<>(HttpStatus.OK, fetchedResource)); } @JsonView(Views.Public.class) @@ -201,7 +199,7 @@ public Mono> createSnapshot(@PathVariable String branchedAp return applicationSnapshotService .createApplicationSnapshot(branchedApplicationId) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @@ -212,7 +210,7 @@ public Mono> getSnapshotWithoutAppli return applicationSnapshotService .getWithoutDataByBranchedApplicationId(branchedApplicationId) - .map(applicationSnapshot -> new ResponseDTO<>(HttpStatus.OK.value(), applicationSnapshot, null)); + .map(applicationSnapshot -> new ResponseDTO<>(HttpStatus.OK, applicationSnapshot)); } @JsonView(Views.Public.class) @@ -222,7 +220,7 @@ public Mono> deleteSnapshotWithoutApplicationJson(@PathVari return applicationSnapshotService .deleteSnapshot(branchedApplicationId) - .map(isDeleted -> new ResponseDTO<>(HttpStatus.OK.value(), isDeleted, null)); + .map(isDeleted -> new ResponseDTO<>(HttpStatus.OK, isDeleted)); } @JsonView(Views.Public.class) @@ -232,7 +230,7 @@ public Mono> restoreSnapshot(@PathVariable String branc return applicationSnapshotService .restoreSnapshot(branchedApplicationId) - .map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null)); + .map(application -> new ResponseDTO<>(HttpStatus.OK, application)); } @JsonView(Views.Public.class) @@ -244,7 +242,7 @@ public Mono> importApplicationFromFile( log.debug("Going to import application in workspace with id: {}", workspaceId); return fileMono.flatMap(file -> importService.extractArtifactExchangeJsonAndSaveArtifact( file, workspaceId, branchedApplicationId)) - .map(fetchedResource -> new ResponseDTO<>(HttpStatus.OK.value(), fetchedResource, null)); + .map(fetchedResource -> new ResponseDTO<>(HttpStatus.OK, fetchedResource)); } @JsonView(Views.Public.class) @@ -253,14 +251,13 @@ public Mono> generateSSHKeyPair( @PathVariable String branchedApplicationId, @RequestParam(required = false) String keyType) { return artifactService .createOrUpdateSshKeyPair(ArtifactType.APPLICATION, branchedApplicationId, keyType) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @GetMapping("/ssh-keypair/{branchedApplicationId}") public Mono> getSSHKey(@PathVariable String branchedApplicationId) { - return service.getSshKey(branchedApplicationId) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + return service.getSshKey(branchedApplicationId).map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -269,7 +266,7 @@ public Mono> update( @PathVariable String branchedApplicationId, @RequestBody Application resource) { log.debug("Going to update resource from base controller with id: {}", branchedApplicationId); return service.updateApplicationWithPresets(branchedApplicationId, resource) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -278,7 +275,7 @@ public Mono> setCurrentTheme( @PathVariable String branchedApplicationId, @PathVariable String themeId) { return themeService .changeCurrentTheme(themeId, branchedApplicationId) - .map(theme -> new ResponseDTO<>(HttpStatus.OK.value(), theme, null)); + .map(theme -> new ResponseDTO<>(HttpStatus.OK, theme)); } @JsonView(Views.Public.class) @@ -287,7 +284,7 @@ public Mono>> getUnConfiguredDatasource( @PathVariable String workspaceId, @RequestParam(name = "defaultApplicationId") String baseApplicationId) { return importService .findDatasourceByArtifactId(workspaceId, baseApplicationId, APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -295,14 +292,14 @@ public Mono>> getUnConfiguredDatasource( public Mono> uploadAppNavigationLogo( @PathVariable String branchedApplicationId, @RequestPart("file") Mono fileMono) { return fileMono.flatMap(part -> service.saveAppNavigationLogo(branchedApplicationId, part)) - .map(url -> new ResponseDTO<>(HttpStatus.OK.value(), url, null)); + .map(url -> new ResponseDTO<>(HttpStatus.OK, url)); } @JsonView(Views.Public.class) @DeleteMapping("/{branchedApplicationId}/logo") public Mono> deleteAppNavigationLogo(@PathVariable String branchedApplicationId) { return service.deleteAppNavigationLogo(branchedApplicationId) - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), null, null)); + .thenReturn(new ResponseDTO<>(HttpStatus.OK, null)); } @JsonView(Views.Public.class) @@ -316,7 +313,7 @@ public Mono> exportApplicationPartially( // params - contains ids of jsLib, actions and datasourceIds to be exported return partialExportService .getPartialExportResources(branchedApplicationId, branchedPageId, fileDTO) - .map(fetchedResource -> new ResponseDTO<>(HttpStatus.OK.value(), fetchedResource, null)); + .map(fetchedResource -> new ResponseDTO<>(HttpStatus.OK, fetchedResource)); } @JsonView(Views.Public.class) @@ -329,8 +326,8 @@ public Mono> importApplicationPartially( @PathVariable String branchedApplicationId, @RequestParam(name = FieldName.PAGE_ID) String branchedPageId) { return fileMono.flatMap(fileData -> partialImportService.importResourceInPage( - workspaceId, branchedApplicationId, branchedPageId, null, fileData)) - .map(fetchedResource -> new ResponseDTO<>(HttpStatus.CREATED.value(), fetchedResource, null)); + workspaceId, branchedApplicationId, branchedPageId, fileData)) + .map(fetchedResource -> new ResponseDTO<>(HttpStatus.CREATED, fetchedResource)); } @JsonView(Views.Public.class) @@ -338,6 +335,6 @@ public Mono> importApplicationPartially( public Mono> importBlock(@RequestBody BuildingBlockDTO buildingBlockDTO) { return partialImportService .importBuildingBlock(buildingBlockDTO) - .map(fetchedResource -> new ResponseDTO<>(HttpStatus.CREATED.value(), fetchedResource, null)); + .map(fetchedResource -> new ResponseDTO<>(HttpStatus.CREATED, fetchedResource)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationTemplateControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationTemplateControllerCE.java index 43b3f6a8507c..e7b48cf1f2b4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationTemplateControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationTemplateControllerCE.java @@ -34,7 +34,7 @@ public ApplicationTemplateControllerCE(ApplicationTemplateService applicationTem public Mono>> getAll() { return applicationTemplateService .getActiveTemplates(null) - .map(templates -> new ResponseDTO<>(HttpStatus.OK.value(), templates, null)); + .map(templates -> new ResponseDTO<>(HttpStatus.OK, templates)); } @JsonView(Views.Public.class) @@ -42,7 +42,7 @@ public Mono>> getAll() { public Mono> getTemplateDetails(@PathVariable String templateId) { return applicationTemplateService .getTemplateDetails(templateId) - .map(templates -> new ResponseDTO<>(HttpStatus.OK.value(), templates, null)); + .map(templates -> new ResponseDTO<>(HttpStatus.OK, templates)); } @JsonView(Views.Public.class) @@ -52,15 +52,13 @@ public Mono>> getSimilarTemplates( return applicationTemplateService .getSimilarTemplates(templateId, params) .collectList() - .map(templates -> new ResponseDTO<>(HttpStatus.OK.value(), templates, null)); + .map(templates -> new ResponseDTO<>(HttpStatus.OK, templates)); } @JsonView(Views.Public.class) @GetMapping("filters") public Mono> getFilters() { - return applicationTemplateService - .getFilters() - .map(filters -> new ResponseDTO<>(HttpStatus.OK.value(), filters, null)); + return applicationTemplateService.getFilters().map(filters -> new ResponseDTO<>(HttpStatus.OK, filters)); } @JsonView(Views.Public.class) @@ -69,7 +67,7 @@ public Mono> importApplicationFromTemplate( @PathVariable String templateId, @PathVariable String workspaceId) { return applicationTemplateService .importApplicationFromTemplate(templateId, workspaceId) - .map(importedApp -> new ResponseDTO<>(HttpStatus.OK.value(), importedApp, null)); + .map(importedApp -> new ResponseDTO<>(HttpStatus.OK, importedApp)); } @JsonView(Views.Public.class) @@ -81,7 +79,7 @@ public Mono> mergeTemplateWithApplication( @RequestBody(required = false) List pagesToImport) { return applicationTemplateService .mergeTemplateWithApplication(templateId, branchedApplicationId, workspaceId, pagesToImport) - .map(importedApp -> new ResponseDTO<>(HttpStatus.OK.value(), importedApp, null)); + .map(importedApp -> new ResponseDTO<>(HttpStatus.OK, importedApp)); } @JsonView(Views.Public.class) @@ -89,7 +87,7 @@ public Mono> mergeTemplateWithApplication( public Mono> publishAsCommunityTemplate(@RequestBody TemplateDTO resource) { return applicationTemplateService .publishAsCommunityTemplate(resource) - .map(template -> new ResponseDTO<>(HttpStatus.OK.value(), template, null)); + .map(template -> new ResponseDTO<>(HttpStatus.OK, template)); } @JsonView(Views.Public.class) @@ -97,6 +95,6 @@ public Mono> publishAsCommunityTemplate(@RequestBody Te public Mono> publishAppsmithTemplate(@RequestBody TemplateDTO resource) { return applicationTemplateService .publishAppsmithTemplate(resource) - .map(template -> new ResponseDTO<>(HttpStatus.OK.value(), template, null)); + .map(template -> new ResponseDTO<>(HttpStatus.OK, template)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ConfigControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ConfigControllerCE.java index 1ed7f46f770e..a0580ea45b88 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ConfigControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ConfigControllerCE.java @@ -26,12 +26,12 @@ public ConfigControllerCE(ConfigService service) { @JsonView(Views.Public.class) @GetMapping("/name/{name}") public Mono> getByName(@PathVariable String name) { - return service.getByName(name).map(resource -> new ResponseDTO<>(HttpStatus.OK.value(), resource, null)); + return service.getByName(name).map(resource -> new ResponseDTO<>(HttpStatus.OK, resource)); } @JsonView(Views.Public.class) @PutMapping("/name/{name}") public Mono> updateByName(@PathVariable String name, @RequestBody Config config) { - return service.updateByName(config).map(resource -> new ResponseDTO<>(HttpStatus.OK.value(), resource, null)); + return service.updateByName(config).map(resource -> new ResponseDTO<>(HttpStatus.OK, resource)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/CustomJSLibControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/CustomJSLibControllerCE.java index b847a402609b..f71b6e2ea918 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/CustomJSLibControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/CustomJSLibControllerCE.java @@ -47,7 +47,7 @@ public Mono> addJSLibToApplication( branchedApplicationId); return customJSLibService .addJSLibsToContext(branchedApplicationId, contextType, Set.of(customJSLib), isForceInstall) - .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK.value(), actionCollection, null)); + .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK, actionCollection)); } @JsonView(Views.Public.class) @@ -64,7 +64,7 @@ public Mono> removeJSLibFromApplication( branchedApplicationId); return customJSLibService .removeJSLibFromContext(branchedApplicationId, contextType, customJSLib, isForceRemove) - .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK.value(), actionCollection, null)); + .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK, actionCollection)); } @JsonView(Views.Public.class) @@ -78,7 +78,7 @@ public Mono>> getAllUserInstalledJSLibInApplicatio branchedContextId); return customJSLibService .getAllJSLibsInContext(branchedContextId, contextType, false) - .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK.value(), actionCollection, null)); + .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK, actionCollection)); } @JsonView(Views.Public.class) @@ -94,6 +94,6 @@ public Mono>> getAllUserInstalledJSLibInApplicatio branchName); return customJSLibService .getAllJSLibsInContext(branchedContextId, contextType, true) - .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK.value(), actionCollection, null)); + .map(actionCollection -> new ResponseDTO<>(HttpStatus.OK, actionCollection)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/DatasourceControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/DatasourceControllerCE.java index 73db8c5ae0f4..9fa60a3c23f3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/DatasourceControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/DatasourceControllerCE.java @@ -62,7 +62,7 @@ public Mono>> getAll(@RequestParam MultiValueMap new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } @JsonView(Views.Public.class) @@ -70,9 +70,7 @@ public Mono>> getAll(@RequestParam MultiValueMap> create(@Valid @RequestBody @JsonView(FromRequest.class) Datasource resource) { log.debug("Going to create resource from datasource controller"); - return datasourceService - .create(resource) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + return datasourceService.create(resource).map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -84,7 +82,7 @@ public Mono> update( log.debug("Going to update resource from datasource controller with id: {}", id); return datasourceService .updateDatasource(id, datasource, environmentId, Boolean.TRUE) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -99,7 +97,7 @@ public Mono> updateDatasourceStorages( return datasourceService .updateDatasourceStorage(datasourceStorageDTO, activeEnvironmentId, Boolean.TRUE) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @@ -108,7 +106,7 @@ public Mono> delete(@PathVariable String id) { log.debug("Going to delete resource from datasource controller with id: {}", id); return datasourceService .archiveById(id) - .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null)); + .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK, deletedResource)); } @JsonView(Views.Public.class) @@ -120,7 +118,7 @@ public Mono> testDatasource( log.debug("Going to test the datasource with id: {}", datasourceStorageDTO.getDatasourceId()); return datasourceService .testDatasource(datasourceStorageDTO, activeEnvironmentId) - .map(testResult -> new ResponseDTO<>(HttpStatus.OK.value(), testResult, null)); + .map(testResult -> new ResponseDTO<>(HttpStatus.OK, testResult)); } @JsonView(Views.Public.class) @@ -132,7 +130,7 @@ public Mono> getStructure( log.debug("Going to get structure for datasource with id: '{}'.", datasourceId); return datasourceStructureSolution .getStructure(datasourceId, BooleanUtils.isTrue(ignoreCache), environmentId) - .map(structure -> new ResponseDTO<>(HttpStatus.OK.value(), structure, null)); + .map(structure -> new ResponseDTO<>(HttpStatus.OK, structure)); } @JsonView(Views.Public.class) @@ -169,9 +167,7 @@ public Mono getAccessToken(AuthorizationCodeCallbackDTO callbackDTO, Serve @JsonView(Views.Public.class) @GetMapping(Url.MOCKS) public Mono>> getMockDataSets() { - return mockDataService - .getMockDataSet() - .map(config -> new ResponseDTO<>(HttpStatus.OK.value(), config.getMockdbs(), null)); + return mockDataService.getMockDataSet().map(config -> new ResponseDTO<>(HttpStatus.OK, config.getMockdbs())); } @JsonView(Views.Public.class) @@ -181,7 +177,7 @@ public Mono> createMockDataSet( @RequestHeader(name = FieldName.HEADER_ENVIRONMENT_ID, required = false) String environmentId) { return mockDataService .createMockDataSet(mockDataSource, environmentId) - .map(datasource -> new ResponseDTO<>(HttpStatus.OK.value(), datasource, null)); + .map(datasource -> new ResponseDTO<>(HttpStatus.OK, datasource)); } @JsonView(Views.Public.class) @@ -193,7 +189,7 @@ public Mono> trigger( log.debug("Trigger received for datasource {}", datasourceId); return datasourceTriggerSolution .trigger(datasourceId, environmentId, triggerRequestDTO) - .map(triggerResultDTO -> new ResponseDTO<>(HttpStatus.OK.value(), triggerResultDTO, null)); + .map(triggerResultDTO -> new ResponseDTO<>(HttpStatus.OK, triggerResultDTO)); } @JsonView(Views.Public.class) @@ -205,6 +201,6 @@ public Mono> getSchemaPreviewData( log.debug("Going to get schema preview data for datasource with id: '{}'.", datasourceId); return datasourceStructureSolution .getSchemaPreviewData(datasourceId, environmentId, template) - .map(actionExecutionResult -> new ResponseDTO<>(HttpStatus.OK.value(), actionExecutionResult, null)); + .map(actionExecutionResult -> new ResponseDTO<>(HttpStatus.OK, actionExecutionResult)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/GitControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/GitControllerCE.java index bb9c05689840..e2976a76dd2a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/GitControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/GitControllerCE.java @@ -66,7 +66,7 @@ public class GitControllerCE { public Mono>> saveGitProfile(@RequestBody GitProfile gitProfile) { log.debug("Going to add default git profile for user"); return service.updateOrCreateGitProfileForCurrentUser(gitProfile) - .map(response -> new ResponseDTO<>(HttpStatus.OK.value(), response, null)); + .map(response -> new ResponseDTO<>(HttpStatus.OK, response)); } @JsonView(Views.Public.class) @@ -75,28 +75,28 @@ public Mono>> saveGitProfile( @PathVariable String baseApplicationId, @RequestBody GitProfile gitProfile) { log.debug("Going to add repo specific git profile for application: {}", baseApplicationId); return service.updateOrCreateGitProfileForCurrentUser(gitProfile, baseApplicationId) - .map(response -> new ResponseDTO<>(HttpStatus.ACCEPTED.value(), response, null)); + .map(response -> new ResponseDTO<>(HttpStatus.ACCEPTED, response)); } @JsonView(Views.Public.class) @GetMapping("/profile/default") public Mono> getDefaultGitConfigForUser() { return service.getDefaultGitProfileOrCreateIfEmpty() - .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK.value(), gitConfigResponse, null)); + .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK, gitConfigResponse)); } @JsonView(Views.Public.class) @GetMapping("/profile/app/{baseApplicationId}") public Mono> getGitConfigForUser(@PathVariable String baseApplicationId) { return service.getGitProfileForUser(baseApplicationId) - .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK.value(), gitConfigResponse, null)); + .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK, gitConfigResponse)); } @JsonView({Views.Metadata.class}) @GetMapping("/metadata/app/{baseArtifactId}") public Mono> getGitMetadata(@PathVariable String baseArtifactId) { return service.getGitArtifactMetadata(baseArtifactId, ArtifactType.APPLICATION) - .map(metadata -> new ResponseDTO<>(HttpStatus.OK.value(), metadata, null)); + .map(metadata -> new ResponseDTO<>(HttpStatus.OK, metadata)); } @JsonView(Views.Public.class) @@ -107,7 +107,7 @@ public Mono> connectApplicationToRemoteRepo( @RequestHeader("Origin") String originHeader) { return service.connectArtifactToGit(baseApplicationId, gitConnectDTO, originHeader, ArtifactType.APPLICATION) .map(artifact -> (Application) artifact) - .map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null)); + .map(application -> new ResponseDTO<>(HttpStatus.OK, application)); } @JsonView(Views.Public.class) @@ -119,7 +119,7 @@ public Mono> commit( @RequestParam(required = false, defaultValue = "false") Boolean doAmend) { log.debug("Going to commit branchedApplicationId {}", branchedApplicationId); return service.commitArtifact(commitDTO, branchedApplicationId, doAmend, ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @@ -128,7 +128,7 @@ public Mono> commit( public Mono> push(@PathVariable String branchedApplicationId) { log.debug("Going to push branchedApplicationId {}", branchedApplicationId); return service.pushArtifact(branchedApplicationId, ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @@ -144,7 +144,7 @@ public Mono> createBranch( srcBranch); return service.createBranch(branchedApplicationId, branchDTO, ArtifactType.APPLICATION) .map(artifact -> (Application) artifact) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @@ -155,7 +155,7 @@ public Mono> checkoutBranch( log.debug("Going to checkout to branch {} application {} ", branchName, branchedApplicationId); return service.checkoutBranch(branchedApplicationId, branchName, true, ArtifactType.APPLICATION) .map(artifact -> (Application) artifact) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -164,7 +164,7 @@ public Mono> disconnectFromRemote(@PathVariable String log.debug("Going to remove the remoteUrl for application {}", branchedApplicationId); return service.detachRemote(branchedApplicationId, ArtifactType.APPLICATION) .map(artifact -> (Application) artifact) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -172,7 +172,7 @@ public Mono> disconnectFromRemote(@PathVariable String public Mono> pull(@PathVariable String branchedApplicationId) { log.debug("Going to pull the latest for branchedApplicationId {}", branchedApplicationId); return service.pullArtifact(branchedApplicationId, ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -183,7 +183,7 @@ public Mono>> branch( log.debug("Going to get branch list for application {}", branchedApplicationId); return service.listBranchForArtifact( branchedApplicationId, BooleanUtils.isTrue(pruneBranches), ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -193,7 +193,7 @@ public Mono> getStatus( @RequestParam(required = false, defaultValue = "true") Boolean compareRemote) { log.debug("Going to get status for default branchedApplicationId {}", branchedApplicationId); return service.getStatus(branchedApplicationId, compareRemote, ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -201,7 +201,7 @@ public Mono> getStatus( public Mono> fetchRemoteChanges(@PathVariable String branchedApplicationId) { log.debug("Going to compare with remote for default branchedApplicationId {}", branchedApplicationId); return service.fetchRemoteChanges(branchedApplicationId, true, ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -214,7 +214,7 @@ public Mono> merge( gitMergeDTO.getDestinationBranch(), branchedApplicationId); return service.mergeBranch(branchedApplicationId, gitMergeDTO, ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -227,13 +227,13 @@ public Mono> mergeStatus( gitMergeDTO.getDestinationBranch(), branchedApplicationId); return service.isBranchMergeable(branchedApplicationId, gitMergeDTO, ArtifactType.APPLICATION) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @GetMapping("/import/keys") public Mono> generateKeyForGitImport(@RequestParam(required = false) String keyType) { - return service.generateSSHKey(keyType).map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + return service.generateSSHKey(keyType).map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -242,7 +242,7 @@ public Mono> importApplicationFromGit( @PathVariable String workspaceId, @RequestBody GitConnectDTO gitConnectDTO) { return service.importArtifactFromGit(workspaceId, gitConnectDTO, ArtifactType.APPLICATION) .map(artifactImportDTO -> (ApplicationImportDTO) artifactImportDTO) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @@ -252,7 +252,7 @@ public Mono> deleteBranch( log.debug("Going to delete branch {} for baseApplicationId {}", branchName, baseArtifactId); return service.deleteBranch(baseArtifactId, branchName, ArtifactType.APPLICATION) .map(artifact -> (Application) artifact) - .map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null)); + .map(application -> new ResponseDTO<>(HttpStatus.OK, application)); } @JsonView(Views.Public.class) @@ -261,7 +261,7 @@ public Mono> discardChanges(@PathVariable String branch log.debug("Going to discard changes for branchedApplicationId {}", branchedApplicationId); return service.discardChanges(branchedApplicationId, ArtifactType.APPLICATION) .map(artifact -> (Application) artifact) - .map(result -> new ResponseDTO<>((HttpStatus.OK.value()), result, null)); + .map(result -> new ResponseDTO<>((HttpStatus.OK), result)); } @JsonView(Views.Public.class) @@ -269,13 +269,13 @@ public Mono> discardChanges(@PathVariable String branch public Mono>> getSupportedKeys() { log.debug("Going to list the list of supported keys"); return Mono.just(GitDeployKeyGenerator.getSupportedProtocols()) - .map(gitDeployKeyDTOS -> new ResponseDTO<>(HttpStatus.OK.value(), gitDeployKeyDTOS, null)); + .map(gitDeployKeyDTOS -> new ResponseDTO<>(HttpStatus.OK, gitDeployKeyDTOS)); } @JsonView(Views.Public.class) @GetMapping("/doc-urls") public Mono>> getGitDocs() { - return service.getGitDocUrls().map(gitDocDTO -> new ResponseDTO<>(HttpStatus.OK.value(), gitDocDTO, null)); + return service.getGitDocUrls().map(gitDocDTO -> new ResponseDTO<>(HttpStatus.OK, gitDocDTO)); } @JsonView(Views.Public.class) @@ -285,14 +285,14 @@ public Mono>> updateProtectedBranches( @RequestBody @Valid BranchProtectionRequestDTO branchProtectionRequestDTO) { return service.updateProtectedBranches( baseArtifactId, branchProtectionRequestDTO.getBranchNames(), ArtifactType.APPLICATION) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @GetMapping("/branch/app/{baseArtifactId}/protected") public Mono>> getProtectedBranches(@PathVariable String baseArtifactId) { return service.getProtectedBranches(baseArtifactId, ArtifactType.APPLICATION) - .map(list -> new ResponseDTO<>(HttpStatus.OK.value(), list, null)); + .map(list -> new ResponseDTO<>(HttpStatus.OK, list)); } @JsonView(Views.Public.class) @@ -300,7 +300,7 @@ public Mono>> getProtectedBranches(@PathVariable String public Mono> autoCommitApplication(@PathVariable String branchedApplicationId) { return autoCommitService .autoCommitApplication(branchedApplicationId) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @@ -309,13 +309,13 @@ public Mono> getAutoCommitProgress( @PathVariable String baseApplicationId, @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { return service.getAutoCommitProgress(baseApplicationId, branchName, ArtifactType.APPLICATION) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @PatchMapping("/auto-commit/toggle/app/{baseArtifactId}") public Mono> toggleAutoCommitEnabled(@PathVariable String baseArtifactId) { return service.toggleAutoCommitEnabled(baseArtifactId, ArtifactType.APPLICATION) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/HealthCheckControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/HealthCheckControllerCE.java index 846514fd6825..898c854abe4f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/HealthCheckControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/HealthCheckControllerCE.java @@ -22,6 +22,6 @@ public class HealthCheckControllerCE { @GetMapping public Mono> getHealth() { log.debug("Checking server health ..."); - return healthCheckService.getHealth().map(health -> new ResponseDTO<>(HttpStatus.OK.value(), health, null)); + return healthCheckService.getHealth().map(health -> new ResponseDTO<>(HttpStatus.OK, health)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/InstanceAdminControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/InstanceAdminControllerCE.java index ab08fec81989..904a54b0353e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/InstanceAdminControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/InstanceAdminControllerCE.java @@ -33,7 +33,7 @@ public class InstanceAdminControllerCE { @GetMapping("/env") public Mono>> getAll() { log.debug("Getting all env configuration"); - return envManager.getAllNonEmpty().map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + return envManager.getAllNonEmpty().map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @Deprecated @@ -44,9 +44,7 @@ public Mono>> getAll() { public Mono> saveEnvChangesJSON( @Valid @RequestBody Map changes, @RequestHeader("Origin") String originHeader) { log.debug("Applying env updates {}", changes.keySet()); - return envManager - .applyChanges(changes, originHeader) - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), null, null)); + return envManager.applyChanges(changes, originHeader).thenReturn(new ResponseDTO<>(HttpStatus.OK, null)); } @JsonView(Views.Public.class) @@ -58,20 +56,20 @@ public Mono> saveEnvChangesMultipartFormData( log.debug("Applying env updates from form data"); return exchange.getMultipartData() .flatMap(formData -> envManager.applyChangesFromMultipartFormData(formData, originHeader)) - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), null, null)); + .thenReturn(new ResponseDTO<>(HttpStatus.OK, null)); } @JsonView(Views.Public.class) @PostMapping("/restart") public Mono> restart() { log.debug("Received restart request"); - return envManager.restart().thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null)); + return envManager.restart().thenReturn(new ResponseDTO<>(HttpStatus.OK, true)); } @JsonView(Views.Public.class) @PostMapping("/send-test-email") public Mono> sendTestEmail(@RequestBody @Valid TestEmailConfigRequestDTO requestDTO) { log.debug("Sending test email"); - return envManager.sendTestEmail(requestDTO).thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null)); + return envManager.sendTestEmail(requestDTO).thenReturn(new ResponseDTO<>(HttpStatus.OK, true)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/LayoutControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/LayoutControllerCE.java index a49f25596c4b..c6585bf1bf2f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/LayoutControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/LayoutControllerCE.java @@ -47,7 +47,7 @@ public LayoutControllerCE( @GetMapping("/{layoutId}/pages/{branchedPageId}") public Mono> getLayout(@PathVariable String branchedPageId, @PathVariable String layoutId) { return service.getLayout(branchedPageId, layoutId, false) - .map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.OK, created)); } @JsonView(Views.Public.class) @@ -57,7 +57,7 @@ public Mono> updateMultipleLayouts( log.debug("update multiple layout received for applicationId {}", applicationId); return updateLayoutService .updateMultipleLayouts(applicationId, request) - .map(updatedCount -> new ResponseDTO<>(HttpStatus.OK.value(), updatedCount, null)); + .map(updatedCount -> new ResponseDTO<>(HttpStatus.OK, updatedCount)); } @JsonView(Views.Public.class) @@ -70,14 +70,14 @@ public Mono> updateLayout( log.debug("update layout received for page {}", branchedPageId); return updateLayoutService .updateLayout(branchedPageId, applicationId, layoutId, dto.toLayout()) - .map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.OK, created)); } @JsonView(Views.Public.class) @GetMapping("/{layoutId}/pages/{branchedPageId}/view") public Mono> getLayoutView(@PathVariable String branchedPageId, @PathVariable String layoutId) { return service.getLayout(branchedPageId, layoutId, true) - .map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.OK, created)); } @JsonView(Views.Public.class) @@ -86,6 +86,6 @@ public Mono> refactorWidgetName(@RequestBody RefactorEnti refactorEntityNameDTO.setEntityType(EntityType.WIDGET); return refactoringService .refactorEntityName(refactorEntityNameDTO) - .map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.OK, created)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/TenantControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/OrganizationControllerCE.java similarity index 50% rename from app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/TenantControllerCE.java rename to app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/OrganizationControllerCE.java index ba34d1029f44..96738de46037 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/TenantControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/OrganizationControllerCE.java @@ -2,10 +2,10 @@ import com.appsmith.external.views.Views; import com.appsmith.server.constants.Url; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.dtos.ResponseDTO; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.fasterxml.jackson.annotation.JsonView; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -18,17 +18,17 @@ import java.util.Map; @Slf4j -@RequestMapping(Url.TENANT_URL) -public class TenantControllerCE { +@RequestMapping(Url.ORGANIZATION_URL) +public class OrganizationControllerCE { - private final TenantService service; + private final OrganizationService service; - public TenantControllerCE(TenantService service) { + public OrganizationControllerCE(OrganizationService service) { this.service = service; } /** - * This API returns the tenant configuration for any user (anonymous or logged in). The configurations are set + * This API returns the organization configuration for any user (anonymous or logged in). The configurations are set * in {@link com.appsmith.server.controllers.ce.InstanceAdminControllerCE#saveEnvChanges(Map)} *

* The update and retrieval are in different controllers because it would have been weird to fetch the configurations @@ -38,15 +38,15 @@ public TenantControllerCE(TenantService service) { */ @JsonView(Views.Public.class) @GetMapping("/current") - public Mono> getTenantConfig() { - log.debug("Attempting to retrieve tenant configuration ... "); - return service.getTenantConfiguration() - .map(resource -> new ResponseDTO<>(HttpStatus.OK.value(), resource, null)); + public Mono> getOrganizationConfig() { + log.debug("Attempting to retrieve organization configuration ... "); + return service.getOrganizationConfiguration().map(resource -> new ResponseDTO<>(HttpStatus.OK, resource)); } @PutMapping("") - public Mono> updateTenantConfiguration(@RequestBody TenantConfiguration tenantConfiguration) { - return service.updateDefaultTenantConfiguration(tenantConfiguration) - .map(tenant -> new ResponseDTO<>(HttpStatus.OK.value(), tenant, null)); + public Mono> updateOrganizationConfiguration( + @RequestBody OrganizationConfiguration organizationConfiguration) { + return service.updateDefaultOrganizationConfiguration(organizationConfiguration) + .map(organization -> new ResponseDTO<>(HttpStatus.OK, organization)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java index 1985ce71d9dc..e2363bfcdce4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java @@ -52,7 +52,7 @@ public Mono> createPage(@Valid @RequestBody PageCreationDTO log.debug("Going to create page {}", page.name()); return applicationPageService .createPage(page.toPageDTO()) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -64,7 +64,7 @@ public Mono> createCRUDPage( log.debug("Going to create crud-page in application {}", resource.getApplicationId()); return createDBTablePageSolution .createPageFromDBTable(null, resource, environmentId, null, Boolean.TRUE) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -77,7 +77,7 @@ public Mono> createCRUDPage( log.debug("Going to create CRUD page {}", branchedPageId); return createDBTablePageSolution .createPageFromDBTable(branchedPageId, resource, environmentId, null, Boolean.TRUE) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @Deprecated @@ -87,7 +87,7 @@ public Mono> getPageNamesByApplicationId( @PathVariable String branchedApplicationId) { return newPageService .findApplicationPagesByBranchedApplicationIdAndViewMode(branchedApplicationId, false, true) - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } @JsonView(Views.Public.class) @@ -97,7 +97,7 @@ public Mono> getPageNamesByApplicationIdInViewM @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { return newPageService .findApplicationPagesByBranchedApplicationIdAndViewMode(branchedApplicationId, true, true) - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } @JsonView(Views.Public.class) @@ -107,7 +107,7 @@ public Mono> getPageById( @RequestParam(required = false, defaultValue = "false") Boolean migrateDsl) { return applicationPageService .getPageAndMigrateDslByBranchedPageId(branchedPageId, false, migrateDsl) - .map(page -> new ResponseDTO<>(HttpStatus.OK.value(), page, null)); + .map(page -> new ResponseDTO<>(HttpStatus.OK, page)); } @JsonView(Views.Public.class) @@ -117,7 +117,7 @@ public Mono> getPageView( @RequestParam(required = false, defaultValue = "false") Boolean migrateDsl) { return applicationPageService .getPageAndMigrateDslByBranchedPageId(branchedPageId, true, migrateDsl) - .map(page -> new ResponseDTO<>(HttpStatus.OK.value(), page, null)); + .map(page -> new ResponseDTO<>(HttpStatus.OK, page)); } /** @@ -135,7 +135,7 @@ public Mono> deletePage(@PathVariable String branchedPageId log.debug("Going to delete page with id: {}", branchedPageId); return applicationPageService .deleteUnpublishedPage(branchedPageId) - .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null)); + .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK, deletedResource)); } @JsonView(Views.Public.class) @@ -143,7 +143,7 @@ public Mono> deletePage(@PathVariable String branchedPageId public Mono> clonePage(@PathVariable String branchedPageId) { return applicationPageService .clonePage(branchedPageId) - .map(page -> new ResponseDTO<>(HttpStatus.CREATED.value(), page, null)); + .map(page -> new ResponseDTO<>(HttpStatus.CREATED, page)); } @JsonView(Views.Public.class) @@ -153,7 +153,7 @@ public Mono> updatePage( log.debug("Going to update page with id: {}", branchedPageId); return newPageService .updatePage(branchedPageId, resource.toPageDTO()) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } /** @@ -180,7 +180,7 @@ public Mono> getAllPages( mode); return newPageService .findApplicationPages(branchedApplicationId, branchedPageId, mode) - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } @JsonView(Views.Public.class) @@ -191,6 +191,6 @@ public Mono> updateDependencyMap( @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { return newPageService .updateDependencyMap(defaultPageId, dependencyMap, RefType.branch, branchName) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PluginControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PluginControllerCE.java index d6323f8b68f6..381186074067 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PluginControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PluginControllerCE.java @@ -44,21 +44,19 @@ public Mono>> getAll(@RequestParam String workspaceId) log.debug("Getting all plugins in workspace {}", workspaceId); return service.getInWorkspace(workspaceId) .collectList() - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } @JsonView(Views.Public.class) @GetMapping("/{pluginId}/form") public Mono> getDatasourceForm(@PathVariable String pluginId) { - return service.getFormConfig(pluginId).map(form -> new ResponseDTO<>(HttpStatus.OK.value(), form, null)); + return service.getFormConfig(pluginId).map(form -> new ResponseDTO<>(HttpStatus.OK, form)); } @JsonView(Views.Public.class) @GetMapping("/default/icons") public Mono>> getDefaultPluginIcons() { - return service.getDefaultPluginIcons() - .collectList() - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + return service.getDefaultPluginIcons().collectList().map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @@ -75,7 +73,7 @@ public Mono> trigger( environmentId, triggerRequestDTO, serverWebExchange.getRequest().getHeaders()) - .map(triggerResultDTO -> new ResponseDTO<>(HttpStatus.OK.value(), triggerResultDTO, null)); + .map(triggerResultDTO -> new ResponseDTO<>(HttpStatus.OK, triggerResultDTO)); } @JsonView(Views.Public.class) @@ -96,6 +94,6 @@ public Mono> triggerMultipart( filePartFlux, requestType, serverWebExchange.getRequest().getHeaders()) - .map(triggerResultDTO -> new ResponseDTO<>(HttpStatus.OK.value(), triggerResultDTO, null)); + .map(triggerResultDTO -> new ResponseDTO<>(HttpStatus.OK, triggerResultDTO)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ProductFeatureAlertControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ProductFeatureAlertControllerCE.java index 48ece64f5c68..b13843a0d8e8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ProductFeatureAlertControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ProductFeatureAlertControllerCE.java @@ -25,9 +25,9 @@ public ProductFeatureAlertControllerCE(ProductAlertService productAlertService) public Mono> generateCode() { return productAlertService.getSingleApplicableMessage().map(messages -> { if (messages.size() > 0) { - return new ResponseDTO<>(HttpStatus.OK.value(), messages.get(0), null); + return new ResponseDTO<>(HttpStatus.OK, messages.get(0)); } else { - return new ResponseDTO<>(HttpStatus.OK.value(), new ProductAlertResponseDTO(), null); + return new ResponseDTO<>(HttpStatus.OK, new ProductAlertResponseDTO()); } }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java index 21099164b830..9a73b444fb77 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/RestApiImportControllerCE.java @@ -50,6 +50,6 @@ public Mono> create( } return service.importAction(input, contextType, contextId, name, workspaceId) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SaasControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SaasControllerCE.java index ce811e005057..3b93c99a43d3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SaasControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SaasControllerCE.java @@ -52,7 +52,7 @@ public Mono> getAppsmithToken( requestAppsmithTokenDTO, serverWebExchange.getRequest().getHeaders(), importForGit) - .map(token -> new ResponseDTO<>(HttpStatus.OK.value(), token, null)); + .map(token -> new ResponseDTO<>(HttpStatus.OK, token)); } @JsonView(Views.Public.class) @@ -65,7 +65,7 @@ public Mono> getAccessToken( log.debug("Received callback for an OAuth2 authorization request"); return authenticationService .getAccessTokenFromCloud(datasourceId, environmentId, appsmithToken) - .map(datasource -> new ResponseDTO<>(HttpStatus.OK.value(), datasource, null)); + .map(datasource -> new ResponseDTO<>(HttpStatus.OK, datasource)); } @GetMapping("authorize") diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SearchEntityControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SearchEntityControllerCE.java index c7b98726a737..9736e4e9181a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SearchEntityControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/SearchEntityControllerCE.java @@ -33,6 +33,6 @@ public Mono> getAllUnpublishedActionCollections( log.debug("Going to search for entities with search string: {}", keyword); return searchEntitySolution .searchEntity(entities, keyword, page, size, Boolean.TRUE) - .map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null)); + .map(resources -> new ResponseDTO<>(HttpStatus.OK, resources)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ThemeControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ThemeControllerCE.java index 1cc71a339086..44c4c3335629 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ThemeControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ThemeControllerCE.java @@ -34,7 +34,7 @@ public class ThemeControllerCE { public Mono>> getApplicationThemes(@PathVariable String branchedApplicationId) { return service.getApplicationThemes(branchedApplicationId) .collectList() - .map(themes -> new ResponseDTO<>(HttpStatus.OK.value(), themes, null)); + .map(themes -> new ResponseDTO<>(HttpStatus.OK, themes)); } @JsonView(Views.Public.class) @@ -43,7 +43,7 @@ public Mono> getCurrentTheme( @PathVariable String branchedApplicationId, @RequestParam(required = false, defaultValue = "EDIT") ApplicationMode mode) { return service.getApplicationTheme(branchedApplicationId, mode) - .map(theme -> new ResponseDTO<>(HttpStatus.OK.value(), theme, null)); + .map(theme -> new ResponseDTO<>(HttpStatus.OK, theme)); } @JsonView(Views.Public.class) @@ -51,13 +51,12 @@ public Mono> getCurrentTheme( public Mono> updateTheme( @PathVariable String branchedApplicationId, @Valid @RequestBody Theme resource) { return service.updateTheme(branchedApplicationId, resource) - .map(theme -> new ResponseDTO<>(HttpStatus.OK.value(), theme, null)); + .map(theme -> new ResponseDTO<>(HttpStatus.OK, theme)); } @JsonView(Views.Public.class) @PatchMapping("{themeId}") public Mono> updateName(@PathVariable String themeId, @Valid @RequestBody Theme resource) { - return service.updateName(themeId, resource) - .map(theme -> new ResponseDTO<>(HttpStatus.OK.value(), theme, null)); + return service.updateName(themeId, resource).map(theme -> new ResponseDTO<>(HttpStatus.OK, theme)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UsagePulseControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UsagePulseControllerCE.java index 3c82234eba7e..4539bebe1d25 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UsagePulseControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UsagePulseControllerCE.java @@ -25,6 +25,6 @@ public class UsagePulseControllerCE { @PostMapping @ResponseStatus(HttpStatus.CREATED) public Mono> create(@RequestBody @Valid UsagePulseDTO usagePulseDTO) { - return service.createPulse(usagePulseDTO).thenReturn(new ResponseDTO<>(HttpStatus.CREATED.value(), true, null)); + return service.createPulse(usagePulseDTO).thenReturn(new ResponseDTO<>(HttpStatus.CREATED, true)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java index b7813b5505bb..dc4ef7cf5913 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java @@ -72,15 +72,13 @@ public Mono createSuperUserFromFormData( @PutMapping() public Mono> update(@RequestBody UserUpdateDTO updates, ServerWebExchange exchange) { return service.updateCurrentUser(updates, exchange) - .map(updatedUser -> new ResponseDTO<>(HttpStatus.OK.value(), updatedUser, null)); + .map(updatedUser -> new ResponseDTO<>(HttpStatus.OK, updatedUser)); } @JsonView(Views.Public.class) @PutMapping("/leaveWorkspace/{workspaceId}") public Mono> leaveWorkspace(@PathVariable String workspaceId) { - return userWorkspaceService - .leaveWorkspace(workspaceId) - .map(user -> new ResponseDTO<>(HttpStatus.OK.value(), user, null)); + return userWorkspaceService.leaveWorkspace(workspaceId).map(user -> new ResponseDTO<>(HttpStatus.OK, user)); } /** @@ -98,14 +96,13 @@ public Mono> forgotPasswordRequest( return service.forgotPasswordTokenGenerate(userPasswordDTO) .defaultIfEmpty(true) .onErrorReturn(true) - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null)); + .thenReturn(new ResponseDTO<>(HttpStatus.OK, true)); } @JsonView(Views.Public.class) @GetMapping("/verifyPasswordResetToken") public Mono> verifyPasswordResetToken(@RequestParam String token) { - return service.verifyPasswordResetToken(token) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + return service.verifyPasswordResetToken(token).map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -113,14 +110,13 @@ public Mono> verifyPasswordResetToken(@RequestParam String public Mono> resetPasswordAfterForgotPassword( @RequestBody ResetUserPasswordDTO userPasswordDTO) { return service.resetPasswordAfterForgotPassword(userPasswordDTO.getToken(), userPasswordDTO) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @GetMapping("/me") public Mono> getUserProfile(@AuthenticationPrincipal User user) { - return service.buildUserProfileDTO(user) - .map(profile -> new ResponseDTO<>(HttpStatus.OK.value(), profile, null)); + return service.buildUserProfileDTO(user).map(profile -> new ResponseDTO<>(HttpStatus.OK, profile)); } /** @@ -139,7 +135,7 @@ public Mono>> inviteUsers( @RequestParam(required = false) String recaptchaToken) { return userAndAccessManagementService .inviteUsers(inviteUsersDTO, originHeader, recaptchaToken) - .map(users -> new ResponseDTO<>(HttpStatus.OK.value(), users, null)); + .map(users -> new ResponseDTO<>(HttpStatus.OK, users)); } @JsonView(Views.Public.class) @@ -148,20 +144,19 @@ public Mono> setReleaseNotesViewed() { return sessionUserService .getCurrentUser() .flatMap(userDataService::setViewedCurrentVersionReleaseNotes) - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), null, null)); + .thenReturn(new ResponseDTO<>(HttpStatus.OK, null)); } @JsonView(Views.Public.class) @PostMapping(value = "/photo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public Mono> uploadProfilePhoto(@RequestPart("file") Mono fileMono) { - return fileMono.flatMap(userDataService::saveProfilePhoto) - .map(url -> new ResponseDTO<>(HttpStatus.OK.value(), url, null)); + return fileMono.flatMap(userDataService::saveProfilePhoto).map(url -> new ResponseDTO<>(HttpStatus.OK, url)); } @JsonView(Views.Public.class) @DeleteMapping("/photo") public Mono> deleteProfilePhoto() { - return userDataService.deleteProfilePhoto().thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), null, null)); + return userDataService.deleteProfilePhoto().thenReturn(new ResponseDTO<>(HttpStatus.OK, null)); } @JsonView(Views.Public.class) @@ -183,9 +178,7 @@ public Mono getProfilePhoto(ServerWebExchange exchange, @PathVariable Stri @JsonView(Views.Public.class) @GetMapping("/features") public Mono>> getFeatureFlags() { - return userDataService - .getFeatureFlagsForCurrentUser() - .map(map -> new ResponseDTO<>(HttpStatus.OK.value(), map, null)); + return userDataService.getFeatureFlagsForCurrentUser().map(map -> new ResponseDTO<>(HttpStatus.OK, map)); } /** @@ -199,7 +192,7 @@ public Mono> resendEmailVerification( @RequestHeader("Origin") String originHeader) { resendEmailVerificationDTO.setBaseUrl(originHeader); return service.resendEmailVerification(resendEmailVerificationDTO, null) - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null)); + .thenReturn(new ResponseDTO<>(HttpStatus.OK, true)); } /** diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java index f8ae8565e8db..a2a3688a80a4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java @@ -37,28 +37,26 @@ public class WorkspaceControllerCE { @JsonView(Views.Public.class) @GetMapping("/{id}") public Mono> getById(@PathVariable String id) { - return service.getById(id).map(workspace -> new ResponseDTO<>(HttpStatus.OK.value(), workspace, null)); + return service.getById(id).map(workspace -> new ResponseDTO<>(HttpStatus.OK, workspace)); } @JsonView(Views.Public.class) @PostMapping @ResponseStatus(HttpStatus.CREATED) public Mono> create(@Valid @RequestBody Workspace resource) { - return service.create(resource).map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + return service.create(resource).map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @PutMapping("/{id}") public Mono> update(@PathVariable String id, @RequestBody Workspace resource) { - return service.update(id, resource) - .map(updatedResource -> new ResponseDTO<>(HttpStatus.OK.value(), updatedResource, null)); + return service.update(id, resource).map(updatedResource -> new ResponseDTO<>(HttpStatus.OK, updatedResource)); } @JsonView(Views.Public.class) @DeleteMapping("/{id}") public Mono> delete(@PathVariable String id) { - return service.archiveById(id) - .map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null)); + return service.archiveById(id).map(deletedResource -> new ResponseDTO<>(HttpStatus.OK, deletedResource)); } /** @@ -69,7 +67,7 @@ public Mono> delete(@PathVariable String id) { public Mono>> getPermissionGroupsForWorkspace( @PathVariable String workspaceId) { return service.getPermissionGroupsForWorkspace(workspaceId) - .map(groupInfoList -> new ResponseDTO<>(HttpStatus.OK.value(), groupInfoList, null)); + .map(groupInfoList -> new ResponseDTO<>(HttpStatus.OK, groupInfoList)); } @JsonView(Views.Public.class) @@ -77,7 +75,7 @@ public Mono>> getPermissionGroupsForWor public Mono>> getUserMembersOfWorkspace(@PathVariable String workspaceId) { return userWorkspaceService .getWorkspaceMembers(workspaceId) - .map(users -> new ResponseDTO<>(HttpStatus.OK.value(), users, null)); + .map(users -> new ResponseDTO<>(HttpStatus.OK, users)); } @JsonView(Views.Public.class) @@ -88,7 +86,7 @@ public Mono> updatePermissionGroupForMember( @RequestHeader(name = "Origin", required = false) String originHeader) { return userWorkspaceService .updatePermissionGroupForMember(workspaceId, updatePermissionGroupDTO, originHeader) - .map(user -> new ResponseDTO<>(HttpStatus.OK.value(), user, null)); + .map(user -> new ResponseDTO<>(HttpStatus.OK, user)); } @JsonView(Views.Public.class) @@ -96,14 +94,13 @@ public Mono> updatePermissionGroupForMember( public Mono> uploadLogo( @PathVariable String workspaceId, @RequestPart("file") Mono fileMono) { return fileMono.flatMap(filePart -> service.uploadLogo(workspaceId, filePart)) - .map(url -> new ResponseDTO<>(HttpStatus.OK.value(), url, null)); + .map(url -> new ResponseDTO<>(HttpStatus.OK, url)); } @JsonView(Views.Public.class) @DeleteMapping("/{workspaceId}/logo") public Mono> deleteLogo(@PathVariable String workspaceId) { - return service.deleteLogo(workspaceId) - .map(workspace -> new ResponseDTO<>(HttpStatus.OK.value(), workspace, null)); + return service.deleteLogo(workspaceId).map(workspace -> new ResponseDTO<>(HttpStatus.OK, workspace)); } @JsonView(Views.Public.class) @@ -112,6 +109,6 @@ public Mono>> workspacesForHome( @RequestHeader(name = "Host", required = false) String hostname) { return userWorkspaceService .getUserWorkspacesByRecentlyUsedOrder(hostname) - .map(workspaces -> new ResponseDTO<>(HttpStatus.OK.value(), workspaces, null)); + .map(workspaces -> new ResponseDTO<>(HttpStatus.OK, workspaces)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java index 9d03ab90ae00..df7decf15976 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java @@ -28,8 +28,10 @@ import com.appsmith.server.repositories.DatasourceRepository; import com.appsmith.server.repositories.NewActionRepository; import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceContextService; import com.appsmith.server.services.FeatureFlagService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SequenceService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.WorkspaceService; @@ -64,6 +66,8 @@ import static com.appsmith.external.constants.spans.DatasourceSpan.FETCH_ALL_DATASOURCES_WITH_STORAGES; import static com.appsmith.external.constants.spans.DatasourceSpan.FETCH_ALL_PLUGINS_IN_WORKSPACE; import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNestedNonNullProperties; +import static com.appsmith.server.constants.ce.FieldNameCE.INSTANCE_ID; +import static com.appsmith.server.constants.ce.FieldNameCE.TENANT_ID; import static com.appsmith.server.dtos.DBOpsType.SAVE; import static com.appsmith.server.helpers.CollectionUtils.isNullOrEmpty; import static com.appsmith.server.helpers.DatasourceAnalyticsUtils.getAnalyticsProperties; @@ -93,6 +97,8 @@ public class DatasourceServiceCEImpl implements DatasourceServiceCE { private final RateLimitService rateLimitService; private final FeatureFlagService featureFlagService; private final ObservationRegistry observationRegistry; + private final OrganizationService organizationService; + private final ConfigService configService; // Defines blocking duration for test as well as connection created for query execution // This will block the creation of datasource connection for 5 minutes, in case of more than 3 failed connection @@ -119,7 +125,9 @@ public DatasourceServiceCEImpl( EnvironmentPermission environmentPermission, RateLimitService rateLimitService, FeatureFlagService featureFlagService, - ObservationRegistry observationRegistry) { + ObservationRegistry observationRegistry, + OrganizationService organizationService, + ConfigService configService) { this.workspaceService = workspaceService; this.sessionUserService = sessionUserService; @@ -138,6 +146,8 @@ public DatasourceServiceCEImpl( this.rateLimitService = rateLimitService; this.featureFlagService = featureFlagService; this.observationRegistry = observationRegistry; + this.organizationService = organizationService; + this.configService = configService; } @Override @@ -223,27 +233,28 @@ private Mono createEx( } return datasourceMono.flatMap(savedDatasource -> this.organiseDatasourceStorages(savedDatasource) - .flatMap(datasourceStorage -> { - // Make sure that we are creating entries only if the id is not already populated - if (hasText(datasourceStorage.getId())) { - return Mono.just(datasourceStorage); - } + .flatMap(datasourceStorageX -> setAdditionalMetadataInDatasourceStorage(datasourceStorageX) + .flatMap(datasourceStorage -> { + // Make sure that we are creating entries only if the id is not already populated + if (hasText(datasourceStorage.getId())) { + return Mono.just(datasourceStorage); + } - return datasourceStorageService - .create(datasourceStorage, isDryOps) - .map(datasourceStorage1 -> { - if (datasourceStorageDryRunQueries != null && isDryOps) { - List datasourceStorages = - datasourceStorageDryRunQueries.get(SAVE); - if (datasourceStorages == null) { - datasourceStorages = new ArrayList<>(); - } - datasourceStorages.add(datasourceStorage1); - datasourceStorageDryRunQueries.put(SAVE, datasourceStorages); - } - return datasourceStorage1; - }); - }) + return datasourceStorageService + .create(datasourceStorage, isDryOps) + .map(datasourceStorage1 -> { + if (datasourceStorageDryRunQueries != null && isDryOps) { + List datasourceStorages = + datasourceStorageDryRunQueries.get(SAVE); + if (datasourceStorages == null) { + datasourceStorages = new ArrayList<>(); + } + datasourceStorages.add(datasourceStorage1); + datasourceStorageDryRunQueries.put(SAVE, datasourceStorages); + } + return datasourceStorage1; + }); + })) .map(datasourceStorageService::createDatasourceStorageDTOFromDatasourceStorage) .collectMap(DatasourceStorageDTO::getEnvironmentId) .map(savedStorages -> { @@ -252,6 +263,20 @@ private Mono createEx( })); } + private Mono setAdditionalMetadataInDatasourceStorage(DatasourceStorage datasourceStorage) { + Mono organizationIdMono = organizationService.getDefaultOrganizationId(); + Mono instanceIdMono = configService.getInstanceId(); + + Map metadata = new HashMap<>(); + + return organizationIdMono.zipWith(instanceIdMono).map(tuple -> { + metadata.put(TENANT_ID, tuple.getT1()); + metadata.put(INSTANCE_ID, tuple.getT2()); + datasourceStorage.setMetadata(metadata); + return datasourceStorage; + }); + } + // this requires an EE override multiple environments protected Flux organiseDatasourceStorages(@NotNull Datasource savedDatasource) { Map storages = savedDatasource.getDatasourceStorages(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceImpl.java index 1fc7bf66b43d..adb06b2f3b3e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceImpl.java @@ -8,8 +8,10 @@ import com.appsmith.server.repositories.DatasourceRepository; import com.appsmith.server.repositories.NewActionRepository; import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceContextService; import com.appsmith.server.services.FeatureFlagService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SequenceService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.WorkspaceService; @@ -41,7 +43,9 @@ public DatasourceServiceImpl( EnvironmentPermission environmentPermission, RateLimitService rateLimitService, FeatureFlagService featureFlagService, - ObservationRegistry observationRegistry) { + ObservationRegistry observationRegistry, + OrganizationService organizationService, + ConfigService configService) { super( repository, @@ -60,6 +64,8 @@ public DatasourceServiceImpl( environmentPermission, rateLimitService, featureFlagService, - observationRegistry); + observationRegistry, + organizationService, + configService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasourcestorages/base/DatasourceStorageServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasourcestorages/base/DatasourceStorageServiceCEImpl.java index 556880330cc5..5b2a16b0f8b9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasourcestorages/base/DatasourceStorageServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasourcestorages/base/DatasourceStorageServiceCEImpl.java @@ -183,6 +183,16 @@ public Mono executePreSaveActions(DatasourceStorage datasourc return pluginExecutorMono.flatMap(pluginExecutor -> pluginExecutor.preSaveHook(datasourceStorage)); } + public Mono executePostSaveActions(DatasourceStorage datasourceStorage) { + Mono pluginMono = pluginService.findById(datasourceStorage.getPluginId()); + Mono pluginExecutorMono = pluginExecutorHelper + .getPluginExecutor(pluginMono) + .switchIfEmpty(Mono.error(new AppsmithException( + AppsmithError.NO_RESOURCE_FOUND, FieldName.PLUGIN, datasourceStorage.getPluginId()))); + + return pluginExecutorMono.flatMap(pluginExecutor -> pluginExecutor.postSaveHook(datasourceStorage)); + } + @Override public Mono validateDatasourceStorage(DatasourceStorage datasourceStorage) { @@ -242,7 +252,10 @@ private Mono validateAndSaveDatasourceStorageToRepository( unsavedDatasourceStorage.updateForBulkWriteOperation(); return Mono.just(unsavedDatasourceStorage); } - return repository.save(unsavedDatasourceStorage).thenReturn(unsavedDatasourceStorage); + return repository + .save(unsavedDatasourceStorage) + .then(this.executePostSaveActions(unsavedDatasourceStorage)) + .thenReturn(unsavedDatasourceStorage); }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Organization.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Organization.java new file mode 100644 index 000000000000..6740f279b216 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Organization.java @@ -0,0 +1,38 @@ +package com.appsmith.server.domains; + +import com.appsmith.external.models.BaseDomain; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldNameConstants; +import org.checkerframework.common.aliasing.qual.Unique; +import org.springframework.data.annotation.Transient; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.io.Serializable; + +@Getter +@Setter +@ToString +@NoArgsConstructor +@Document +@FieldNameConstants +public class Organization extends BaseDomain implements Serializable { + + @Unique String slug; + + String displayName; + + @Transient + String instanceId; + + @Transient + String adminEmailDomainHash; + + PricingPlan pricingPlan; + + OrganizationConfiguration organizationConfiguration; + + // TODO add SSO and other configurations here after migrating from environment variables to database configuration +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/OrganizationConfiguration.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/OrganizationConfiguration.java new file mode 100644 index 000000000000..5be0df072461 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/OrganizationConfiguration.java @@ -0,0 +1,9 @@ +package com.appsmith.server.domains; + +import com.appsmith.server.domains.ce.OrganizationConfigurationCE; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class OrganizationConfiguration extends OrganizationConfigurationCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PermissionGroup.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PermissionGroup.java index fcb44cdc2e4f..52729bd50e55 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PermissionGroup.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PermissionGroup.java @@ -21,8 +21,12 @@ public class PermissionGroup extends BaseDomain { @NotNull String name; + @Deprecated + // TODO: Remove this field once we have migrated the data to use organizationId instead of tenantId String tenantId; + String organizationId; + String description; // TODO: refactor this to defaultDocumentId, as we can use this to store associated document id for diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PricingPlan.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PricingPlan.java index b216f0c78faf..3fc13de97019 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PricingPlan.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/PricingPlan.java @@ -1,7 +1,7 @@ package com.appsmith.server.domains; /** - * Deprecated since we use plans based on the license and this information is stored inside license tenant pricingPlan is no longer used + * Deprecated since we use plans based on the license and this information is stored inside license organization pricingPlan is no longer used */ @Deprecated public enum PricingPlan { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java index f4a005bbff76..53f97fae68b6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Tenant.java @@ -12,6 +12,8 @@ import java.io.Serializable; +@Deprecated +// This class has been deprecated. Please use Organization instead. @Getter @Setter @ToString diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/TenantConfiguration.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/TenantConfiguration.java index e4b293b814a7..ccae88485bd5 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/TenantConfiguration.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/TenantConfiguration.java @@ -4,6 +4,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; +@Deprecated @Data @EqualsAndHashCode(callSuper = true) public class TenantConfiguration extends TenantConfigurationCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UsagePulse.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UsagePulse.java index 36ed0e074d83..03637199c319 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UsagePulse.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/UsagePulse.java @@ -15,7 +15,11 @@ public class UsagePulse extends BaseDomain { // Hashed user email private String user; private String instanceId; - private String tenantId; + private String organizationId; private Boolean viewMode; private Boolean isAnonymousUser; + + @Deprecated + // TODO: Remove this field once we have migrated the data to use organizationId instead of tenantId + private String tenantId; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java index a2444c5ac74e..87b211f2cd03 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java @@ -76,9 +76,14 @@ public class User extends BaseDomain implements UserDetails, OidcUser { @JsonView(Views.Public.class) Boolean isAnonymous = false; + @Deprecated + // TODO: Remove this field once we have migrated the data to use organizationId instead of tenantId @JsonView(Views.Public.class) private String tenantId; + @JsonView(Views.Public.class) + private String organizationId; + // Field to indicate if the user is system generated or not. Expected to be `true` for system generated users, null // otherwise. // e.g. AnonymousUser is created by the system migration during the first time startup. diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java index 8e72b4b98d9c..49f8fc3afa82 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Workspace.java @@ -47,9 +47,14 @@ public class Workspace extends BaseDomain { @JsonView(Views.Internal.class) private String logoAssetId; + @Deprecated + // TODO: Remove this field once we have migrated the data to use organizationId instead of tenantId @JsonView(Views.Public.class) private String tenantId; + @JsonView(Views.Public.class) + private String organizationId; + @JsonView(Views.Internal.class) private Boolean hasEnvironments; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationCE.java index e00580ef8831..787a85106810 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationCE.java @@ -368,7 +368,7 @@ public void setApplicationDetail(ApplicationDetail applicationDetail) { } @Override - @JsonView({Views.Internal.class}) + @JsonView({Views.Public.class}) public ArtifactType getArtifactType() { return ArtifactType.APPLICATION; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/OrganizationConfigurationCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/OrganizationConfigurationCE.java new file mode 100644 index 000000000000..a8cd697d5594 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/OrganizationConfigurationCE.java @@ -0,0 +1,91 @@ +package com.appsmith.server.domains.ce; + +import com.appsmith.external.enums.FeatureFlagEnum; +import com.appsmith.server.constants.FeatureMigrationType; +import com.appsmith.server.constants.LicensePlan; +import com.appsmith.server.constants.MigrationStatus; +import com.appsmith.server.domains.License; +import com.appsmith.server.domains.OrganizationConfiguration; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; +import org.apache.commons.lang3.ObjectUtils; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Data +public class OrganizationConfigurationCE implements Serializable { + + private String googleMapsKey; + + private Boolean isFormLoginEnabled; + + private String instanceName; + + protected License license; + + // organization admin can toggle this field to enable/disable email verification + private Boolean emailVerificationEnabled; + + // We add `JsonInclude` here, so that this field is included in the JSON response, even if it is `null`. Reason is, + // if this field is not present, then the existing value in client's state doesn't get updated. It's just the way + // the splat (`...`) operator works in the client. Evidently, we'll want this for all fields in this class. + // In that sense, this class is special, because organization configuration is cached in `localStorage`, and so it's + // state + // is preserved across browser refreshes. + @JsonInclude + private List thirdPartyAuths; + + // Field to be used to track the status of migrations during upgrade and downgrade workflows. Downgrade migrations + // are gated by user consent whereas upgrade can be triggered immediately and depending upon the status client + // blocks the user access to the instance + MigrationStatus migrationStatus = MigrationStatus.COMPLETED; + + // Field to store the list of features for which the migrations are pending. This will be used to store the diffs of + // the feature flags. This can happen for 2 reasons: + // 1. The license plan changes + // 2. Because of grandfathering via cron where organization level feature flags are fetched + Map featuresWithPendingMigration; + + // This variable is used to indicate if the server needs to be restarted after the migration based on feature flags + // is complete. + Boolean isRestartRequired; + + Boolean isStrongPasswordPolicyEnabled; + + private Boolean isAtomicPushAllowed = false; + + public void addThirdPartyAuth(String auth) { + if (thirdPartyAuths == null) { + thirdPartyAuths = new ArrayList<>(); + } + thirdPartyAuths.add(auth); + } + + public void copyNonSensitiveValues(OrganizationConfiguration organizationConfiguration) { + license = new License(); + license.setPlan(LicensePlan.FREE); + + if (organizationConfiguration == null) { + return; + } + + googleMapsKey = ObjectUtils.defaultIfNull(organizationConfiguration.getGoogleMapsKey(), googleMapsKey); + isFormLoginEnabled = + ObjectUtils.defaultIfNull(organizationConfiguration.getIsFormLoginEnabled(), isFormLoginEnabled); + instanceName = ObjectUtils.defaultIfNull(organizationConfiguration.getInstanceName(), instanceName); + emailVerificationEnabled = ObjectUtils.defaultIfNull( + organizationConfiguration.isEmailVerificationEnabled(), emailVerificationEnabled); + + featuresWithPendingMigration = organizationConfiguration.getFeaturesWithPendingMigration(); + migrationStatus = organizationConfiguration.getMigrationStatus(); + isStrongPasswordPolicyEnabled = organizationConfiguration.getIsStrongPasswordPolicyEnabled(); + isAtomicPushAllowed = organizationConfiguration.getIsAtomicPushAllowed(); + } + + public Boolean isEmailVerificationEnabled() { + return Boolean.TRUE.equals(this.emailVerificationEnabled); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java index 74a62527e47c..29f5e4e84bb3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Map; +@Deprecated @Data public class TenantConfigurationCE implements Serializable { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/FeaturesRequestDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/FeaturesRequestDTO.java index f18672b49a58..d1f61bd79f39 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/FeaturesRequestDTO.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/FeaturesRequestDTO.java @@ -7,7 +7,7 @@ @Setter public class FeaturesRequestDTO { private String instanceId; - private String tenantId; + private String organizationId; private String appsmithVersion; private Boolean isCloudHosting; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ResponseDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ResponseDTO.java index 85a701b6ce0f..65fad132938e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ResponseDTO.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ResponseDTO.java @@ -6,6 +6,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import org.springframework.http.HttpStatus; import java.io.Serializable; @@ -22,6 +23,10 @@ public class ResponseDTO implements Serializable { private T data; + public ResponseDTO(HttpStatus status, T data) { + this(status.value(), data, null); + } + public ResponseDTO(int status, T data, String message) { this.responseMeta = new ResponseMetaDTO(status, message); this.data = data; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSessionDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSessionDTO.java index 92b6adab46e8..9767c1ae6232 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSessionDTO.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserSessionDTO.java @@ -45,7 +45,7 @@ public class UserSessionDTO { private Set workspaceIds; - private String tenantId; + private String organizationId; private Object credentials; @@ -85,7 +85,7 @@ public static UserSessionDTO fromToken(Authentication authentication) { session.state = user.getState(); session.isEnabled = user.isEnabled(); session.workspaceIds = user.getWorkspaceIds(); - session.tenantId = user.getTenantId(); + session.organizationId = user.getOrganizationId(); session.emailVerified = Boolean.TRUE.equals(user.getEmailVerified()); session.emailVerificationRequired = Boolean.TRUE.equals(user.getEmailVerificationRequired()); @@ -126,7 +126,7 @@ public Authentication makeToken() { user.setState(state); user.setIsEnabled(isEnabled); user.setWorkspaceIds(workspaceIds); - user.setTenantId(tenantId); + user.setOrganizationId(organizationId); user.setEmailVerified(Boolean.TRUE.equals(emailVerified)); user.setEmailVerificationRequired(Boolean.TRUE.equals(emailVerificationRequired)); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ConsolidatedAPIResponseCE_DTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ConsolidatedAPIResponseCE_DTO.java index d51d75e23b2c..a9eb001f8a63 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ConsolidatedAPIResponseCE_DTO.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ConsolidatedAPIResponseCE_DTO.java @@ -3,8 +3,8 @@ import com.appsmith.external.models.ActionDTO; import com.appsmith.external.models.Datasource; import com.appsmith.server.domains.CustomJSLib; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.Plugin; -import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.Theme; import com.appsmith.server.dtos.ActionCollectionDTO; import com.appsmith.server.dtos.ActionCollectionViewDTO; @@ -36,7 +36,7 @@ public class ConsolidatedAPIResponseCE_DTO { ResponseDTO> featureFlags; /* v1/tenants/current */ - ResponseDTO tenantConfig; + ResponseDTO organizationConfig; /* v1/product-alert/alert */ ResponseDTO productAlert; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java index 1a9e705fb383..49df751a001e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java @@ -912,9 +912,9 @@ public enum AppsmithError { ErrorType.INTERNAL_ERROR, null), - TENANT_EMAIL_VERIFICATION_NOT_ENABLED( + ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED( 400, - AppsmithErrorCode.TENANT_EMAIL_VERIFICATION_NOT_ENABLED.getCode(), + AppsmithErrorCode.ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED.getCode(), "Email verification is not enabled. Please contact your admin", AppsmithErrorAction.DEFAULT, "Email verification not enabled", diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithErrorCode.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithErrorCode.java index 4824f9815e22..44b154674c90 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithErrorCode.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithErrorCode.java @@ -123,7 +123,7 @@ public enum AppsmithErrorCode { USER_EMAIL_ALREADY_VERIFIED("AE-EMV-4095", "User email already verified"), EMAIL_VERIFICATION_TOKEN_EXPIRED("AE-EMV-4096", "Email Verification Token expired"), - TENANT_EMAIL_VERIFICATION_NOT_ENABLED("AE-EMV-4097", "Email Verification not enabled"), + ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED("AE-EMV-4097", "Email Verification not enabled"), INVALID_EMAIL_VERIFICATION("AE-EMV-4098", "Invalid email verification request"), diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagIdentityTraits.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagIdentityTraits.java index 204c93c8bb94..f87209b01652 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagIdentityTraits.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagIdentityTraits.java @@ -18,7 +18,7 @@ @AllArgsConstructor public class FeatureFlagIdentityTraits { String instanceId; - String tenantId; + String organizationId; Set userIdentifiers; Map traits; String appsmithVersion; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitApplicationControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitApplicationControllerCE.java index a631781b9bae..eb536229e1bb 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitApplicationControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitApplicationControllerCE.java @@ -61,7 +61,7 @@ public class GitApplicationControllerCE { public Mono> getGitMetadata(@PathVariable String baseApplicationId) { return centralGitService .getGitArtifactMetadata(baseApplicationId, ARTIFACT_TYPE) - .map(metadata -> new ResponseDTO<>(HttpStatus.OK.value(), metadata, null)); + .map(metadata -> new ResponseDTO<>(HttpStatus.OK, metadata)); } @JsonView(Views.Public.class) @@ -72,7 +72,7 @@ public Mono> connectApplicationToRemoteRepo( @RequestHeader("Origin") String originHeader) { return centralGitService .connectArtifactToGit(applicationId, ARTIFACT_TYPE, gitConnectDTO, originHeader, GIT_TYPE) - .map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null)); + .map(application -> new ResponseDTO<>(HttpStatus.OK, application)); } @JsonView(Views.Public.class) @@ -83,7 +83,7 @@ public Mono> commit( log.info("Going to commit branchedApplicationId {}", branchedApplicationId); return centralGitService .commitArtifact(commitDTO, branchedApplicationId, ARTIFACT_TYPE, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @@ -99,7 +99,7 @@ public Mono> createReference( srcBranch); return centralGitService .createReference(referencedApplicationId, ARTIFACT_TYPE, gitRefDTO, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @@ -108,7 +108,7 @@ public Mono> checkoutReference( @PathVariable String referencedApplicationId, @RequestBody GitRefDTO gitRefDTO) { return centralGitService .checkoutReference(referencedApplicationId, ARTIFACT_TYPE, gitRefDTO, true, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -117,7 +117,7 @@ public Mono> disconnectFromRemote(@PathVariable log.info("Going to remove the remoteUrl for application {}", branchedApplicationId); return centralGitService .detachRemote(branchedApplicationId, ARTIFACT_TYPE, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -126,7 +126,7 @@ public Mono> pull(@PathVariable String branchedApplicati log.info("Going to pull the latest for branchedApplicationId {}", branchedApplicationId); return centralGitService .pullArtifact(branchedApplicationId, ARTIFACT_TYPE, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -137,7 +137,7 @@ public Mono> getStatus( log.info("Going to get status for branchedApplicationId {}", branchedApplicationId); return centralGitService .getStatus(branchedApplicationId, ARTIFACT_TYPE, compareRemote, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -148,7 +148,7 @@ public Mono> fetchRemoteChanges( log.info("Going to compare with remote for default referencedApplicationId {}", referencedApplicationId); return centralGitService .fetchRemoteChanges(referencedApplicationId, ARTIFACT_TYPE, true, GIT_TYPE, refType) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -162,7 +162,7 @@ public Mono> merge( branchedApplicationId); return centralGitService .mergeBranch(branchedApplicationId, ARTIFACT_TYPE, gitMergeDTO, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -176,7 +176,7 @@ public Mono> mergeStatus( branchedApplicationId); return centralGitService .isBranchMergable(branchedApplicationId, ARTIFACT_TYPE, gitMergeDTO, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -188,7 +188,7 @@ public Mono> deleteBranch( log.info("Going to delete ref {} for baseApplicationId {}", refName, baseArtifactId); return centralGitService .deleteGitReference(baseArtifactId, ARTIFACT_TYPE, refName, refType, GIT_TYPE) - .map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null)); + .map(application -> new ResponseDTO<>(HttpStatus.OK, application)); } @JsonView(Views.Public.class) @@ -197,7 +197,7 @@ public Mono> discardChanges(@PathVariable String log.info("Going to discard changes for branchedApplicationId {}", branchedApplicationId); return centralGitService .discardChanges(branchedApplicationId, ARTIFACT_TYPE, GIT_TYPE) - .map(result -> new ResponseDTO<>((HttpStatus.OK.value()), result, null)); + .map(result -> new ResponseDTO<>((HttpStatus.OK), result)); } @JsonView(Views.Public.class) @@ -207,7 +207,7 @@ public Mono>> updateProtectedBranches( @RequestBody @Valid BranchProtectionRequestDTO branchProtectionRequestDTO) { return centralGitService .updateProtectedBranches(baseArtifactId, ARTIFACT_TYPE, branchProtectionRequestDTO.getBranchNames()) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @@ -215,7 +215,7 @@ public Mono>> updateProtectedBranches( public Mono>> getProtectedBranches(@PathVariable String baseArtifactId) { return centralGitService .getProtectedBranches(baseArtifactId, ARTIFACT_TYPE) - .map(list -> new ResponseDTO<>(HttpStatus.OK.value(), list, null)); + .map(list -> new ResponseDTO<>(HttpStatus.OK, list)); } @JsonView(Views.Public.class) @@ -223,7 +223,7 @@ public Mono>> getProtectedBranches(@PathVariable String public Mono> autoCommitApplication(@PathVariable String branchedApplicationId) { return autoCommitService .autoCommitApplication(branchedApplicationId) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @@ -233,7 +233,7 @@ public Mono> getAutoCommitProgress( @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { return centralGitService .getAutoCommitProgress(baseApplicationId, ARTIFACT_TYPE, branchName) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @@ -241,7 +241,7 @@ public Mono> getAutoCommitProgress( public Mono> toggleAutoCommitEnabled(@PathVariable String baseArtifactId) { return centralGitService .toggleAutoCommitEnabled(baseArtifactId, ARTIFACT_TYPE) - .map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null)); + .map(data -> new ResponseDTO<>(HttpStatus.OK, data)); } @JsonView(Views.Public.class) @@ -254,7 +254,7 @@ public Mono>> getReferences( return centralGitService .listBranchForArtifact( branchedApplicationId, ARTIFACT_TYPE, BooleanUtils.isTrue(pruneBranches), GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } @JsonView(Views.Public.class) @@ -262,7 +262,7 @@ public Mono>> getReferences( public Mono> getSSHKey(@PathVariable String branchedApplicationId) { return artifactService .getSshKey(ARTIFACT_TYPE, branchedApplicationId) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } @JsonView(Views.Public.class) @@ -271,6 +271,6 @@ public Mono> generateSSHKeyPair( @PathVariable String branchedApplicationId, @RequestParam(required = false) String keyType) { return artifactService .createOrUpdateSshKeyPair(ARTIFACT_TYPE, branchedApplicationId, keyType) - .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); + .map(created -> new ResponseDTO<>(HttpStatus.CREATED, created)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitArtifactControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitArtifactControllerCE.java index 785fffa64ea3..377c3976b016 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitArtifactControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/controllers/GitArtifactControllerCE.java @@ -51,7 +51,7 @@ public Mono>> saveGitProfile(@RequestBody Gi log.debug("Going to add default git profile for user"); return gitProfileUtils .updateOrCreateGitProfileForCurrentUser(gitProfile) - .map(response -> new ResponseDTO<>(HttpStatus.OK.value(), response, null)); + .map(response -> new ResponseDTO<>(HttpStatus.OK, response)); } @JsonView(Views.Public.class) @@ -59,7 +59,7 @@ public Mono>> saveGitProfile(@RequestBody Gi public Mono> getDefaultGitConfigForUser() { return gitProfileUtils .getDefaultGitProfileOrCreateIfEmpty() - .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK.value(), gitConfigResponse, null)); + .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK, gitConfigResponse)); } @JsonView(Views.Public.class) @@ -69,7 +69,7 @@ public Mono>> saveGitProfile( log.debug("Going to add repo specific git profile for application: {}", baseApplicationId); return gitProfileUtils .updateOrCreateGitProfileForCurrentUser(gitProfile, baseApplicationId) - .map(response -> new ResponseDTO<>(HttpStatus.ACCEPTED.value(), response, null)); + .map(response -> new ResponseDTO<>(HttpStatus.ACCEPTED, response)); } @JsonView(Views.Public.class) @@ -77,7 +77,7 @@ public Mono>> saveGitProfile( public Mono> getGitConfigForUser(@PathVariable String baseArtifactId) { return gitProfileUtils .getGitProfileForUser(baseArtifactId) - .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK.value(), gitConfigResponse, null)); + .map(gitConfigResponse -> new ResponseDTO<>(HttpStatus.OK, gitConfigResponse)); } @JsonView(Views.Public.class) @@ -88,15 +88,13 @@ public Mono> importArtifactFromGit( // TODO: remove artifact type from methods. return centralGitService .importArtifactFromGit(workspaceId, gitConnectDTO, GIT_TYPE) - .map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null)); + .map(result -> new ResponseDTO<>(HttpStatus.CREATED, result)); } @JsonView(Views.Public.class) @GetMapping("/doc-urls") public Mono>> getGitDocs() { - return centralGitService - .getGitDocUrls() - .map(gitDocDTO -> new ResponseDTO<>(HttpStatus.OK.value(), gitDocDTO, null)); + return centralGitService.getGitDocUrls().map(gitDocDTO -> new ResponseDTO<>(HttpStatus.OK, gitDocDTO)); } @JsonView(Views.Public.class) @@ -104,14 +102,12 @@ public Mono>> getGitDocs() { public Mono>> getSupportedKeys() { log.info("Going to list the list of supported keys"); return Mono.just(GitDeployKeyGenerator.getSupportedProtocols()) - .map(gitDeployKeyDTOS -> new ResponseDTO<>(HttpStatus.OK.value(), gitDeployKeyDTOS, null)); + .map(gitDeployKeyDTOS -> new ResponseDTO<>(HttpStatus.OK, gitDeployKeyDTOS)); } @JsonView(Views.Public.class) @GetMapping("/import/keys") public Mono> generateKeyForGitImport(@RequestParam(required = false) String keyType) { - return centralGitService - .generateSSHKey(keyType) - .map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null)); + return centralGitService.generateSSHKey(keyType).map(result -> new ResponseDTO<>(HttpStatus.OK, result)); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java index df6fc99f9afc..f4b6aa4daa93 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java @@ -215,13 +215,15 @@ public Mono updateImportedRepositoryDetails( String workspaceId = jsonTransformationDTO.getWorkspaceId(); String placeHolder = jsonTransformationDTO.getBaseArtifactId(); String repoName = jsonTransformationDTO.getRepoName(); - Path temporaryStorage = Path.of(workspaceId, placeHolder, repoName); + Path temporaryArtifactPath = Path.of(workspaceId, placeHolder); ArtifactType artifactType = baseArtifact.getArtifactType(); GitArtifactHelper gitArtifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType); - Path newPath = gitArtifactHelper.getRepoSuffixPath(workspaceId, baseArtifact.getId(), repoName); + Path absoluteArtifactPath = gitArtifactHelper + .getRepoSuffixPath(workspaceId, baseArtifact.getId(), repoName) + .getParent(); - return commonGitFileUtils.moveArtifactFromTemporaryToBaseArtifactIdRepository(temporaryStorage, newPath); + return commonGitFileUtils.moveRepositoryFromTemporaryStorage(temporaryArtifactPath, absoluteArtifactPath); } @Override @@ -237,29 +239,29 @@ public Mono fetchRemoteRepository( repoSuffix, gitConnectDTO.getRemoteUrl(), gitAuth.getPrivateKey(), gitAuth.getPublicKey()) .onErrorResume(error -> { log.error("Error while cloning the remote repo, {}", error.getMessage()); - return gitAnalyticsUtils - .addAnalyticsForGitOperation( - AnalyticsEvents.GIT_IMPORT, - artifact, - error.getClass().getName(), - error.getMessage(), - false) - .flatMap(user -> commonGitFileUtils - .deleteLocalRepo(repoSuffix) - .then(gitArtifactHelper.deleteArtifact(artifact.getId()))) - .flatMap(artifact1 -> { - if (error instanceof TransportException) { - return Mono.error( - new AppsmithException(AppsmithError.INVALID_GIT_SSH_CONFIGURATION)); - } else if (error instanceof InvalidRemoteException) { - return Mono.error( - new AppsmithException(AppsmithError.INVALID_PARAMETER, "remote url")); - } else if (error instanceof TimeoutException) { - return Mono.error(new AppsmithException(AppsmithError.GIT_EXECUTION_TIMEOUT)); - } - return Mono.error(new AppsmithException( - AppsmithError.GIT_ACTION_FAILED, "clone", error.getMessage())); - }); + + Mono deleteLocalRepoMono = commonGitFileUtils.deleteLocalRepo(repoSuffix); + Mono errorAnalyticsMono = gitAnalyticsUtils.addAnalyticsForGitOperation( + AnalyticsEvents.GIT_IMPORT, + artifact, + error.getClass().getName(), + error.getMessage(), + false); + + AppsmithException appsmithException; + + if (error instanceof TransportException) { + appsmithException = new AppsmithException(AppsmithError.INVALID_GIT_SSH_CONFIGURATION); + } else if (error instanceof InvalidRemoteException) { + appsmithException = new AppsmithException(AppsmithError.INVALID_PARAMETER, "remote url"); + } else if (error instanceof TimeoutException) { + appsmithException = new AppsmithException(AppsmithError.GIT_EXECUTION_TIMEOUT); + } else { + appsmithException = + new AppsmithException(AppsmithError.GIT_ACTION_FAILED, "clone", error.getMessage()); + } + + return deleteLocalRepoMono.zipWith(errorAnalyticsMono).then(Mono.error(appsmithException)); }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java index afa9819ce76d..57fda98d43da 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java @@ -1,12 +1,12 @@ package com.appsmith.server.helpers; import com.appsmith.server.helpers.ce.EmailServiceHelperCEImpl; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import org.springframework.stereotype.Component; @Component public class EmailServiceHelperImpl extends EmailServiceHelperCEImpl implements EmailServiceHelper { - public EmailServiceHelperImpl(TenantService tenantService) { - super(tenantService); + public EmailServiceHelperImpl(OrganizationService organizationService) { + super(organizationService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java index cbf2e123c357..b409e60b3436 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java @@ -8,7 +8,7 @@ public class InMemoryCacheableRepositoryHelper { private Set anonymousUserPermissionGroupIds = null; - private String defaultTenantId = null; + private String defaultOrganizationId = null; private String instanceAdminPermissionGroupId = null; @@ -20,12 +20,12 @@ public void setAnonymousUserPermissionGroupIds(Set anonymousUserPermissi this.anonymousUserPermissionGroupIds = anonymousUserPermissionGroupIds; } - public String getDefaultTenantId() { - return defaultTenantId; + public String getDefaultOrganizationId() { + return defaultOrganizationId; } - public void setDefaultTenantId(String defaultTenantId) { - this.defaultTenantId = defaultTenantId; + public void setDefaultOrganizationId(String defaultOrganizationId) { + this.defaultOrganizationId = defaultOrganizationId; } public void setInstanceAdminPermissionGroupId(String instanceAdminPermissionGroupId) { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java index bd0849e28971..cffb9b9b89c6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java @@ -143,9 +143,9 @@ protected ArtifactGitFileUtils getArtifactBasedFileHelper(ArtifactType artifa * This method will save the complete application in the local repo directory. * Path to repo will be : ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/{application_data} * - * @param baseRepoSuffix path suffix used to create a local repo path + * @param baseRepoSuffix path suffix used to create a local repo path * @param artifactExchangeJson application reference object from which entire application can be rehydrated - * @param branchName name of the branch for the current application + * @param branchName name of the branch for the current application * @return repo path where the application is stored */ public Mono saveArtifactToLocalRepo( @@ -662,9 +662,9 @@ && hasText(jsonTransformationDTO.getBaseArtifactId()) /** * Method to reconstruct the application from the local git repo * - * @param workspaceId To which workspace application needs to be rehydrated + * @param workspaceId To which workspace application needs to be rehydrated * @param baseArtifactId Root application for the current branched application - * @param branchName for which branch the application needs to rehydrate + * @param branchName for which branch the application needs to rehydrate * @param artifactType * @return application reference from which entire application can be rehydrated */ @@ -786,17 +786,31 @@ public Mono> reconstructMetadataFromRepo( }); } - public Mono moveArtifactFromTemporaryToBaseArtifactIdRepository( - Path currentRepositoryPath, Path newRepositoryPath) { - Path currentGitPath = Path.of(gitServiceConfig.getGitRootPath()).resolve(currentRepositoryPath); - Path targetPath = Path.of(gitServiceConfig.getGitRootPath()).resolve(newRepositoryPath); + public Mono moveRepositoryFromTemporaryStorage(Path temporaryPath, Path absoluteArtifactPath) { + + Path currentGitPath = Path.of(gitServiceConfig.getGitRootPath()).resolve(temporaryPath); + Path targetPath = Path.of(gitServiceConfig.getGitRootPath()).resolve(absoluteArtifactPath); return Mono.fromCallable(() -> { - if (!Files.exists(targetPath)) { - Files.createDirectories(targetPath); - } + try { + if (!Files.exists(targetPath)) { + Files.createDirectories(targetPath); + } - return Files.move(currentGitPath, targetPath, REPLACE_EXISTING); + return Files.move(currentGitPath, targetPath, REPLACE_EXISTING); + + } catch (IOException exception) { + log.error("File IO exception while moving repository. {}", exception.getMessage()); + throw new AppsmithException(AppsmithError.GIT_FILE_SYSTEM_ERROR, exception.getMessage()); + } + }) + .onErrorResume(error -> { + log.error( + "Error while moving repository from temporary storage {} to permanent storage {}", + currentGitPath, + targetPath, + error.getMessage()); + return Mono.error(error); }) .subscribeOn(Schedulers.boundedElastic()); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java index 2dca84c12c4f..239be2322bc7 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java @@ -1,7 +1,7 @@ package com.appsmith.server.helpers.ce; -import com.appsmith.server.domains.TenantConfiguration; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.domains.OrganizationConfiguration; +import com.appsmith.server.services.OrganizationService; import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; @@ -23,13 +23,14 @@ @AllArgsConstructor public class EmailServiceHelperCEImpl implements EmailServiceHelperCE { - private final TenantService tenantService; + private final OrganizationService organizationService; @Override public Mono> enrichWithBrandParams(Map params, String origin) { - return tenantService.getTenantConfiguration().map(tenant -> { - final TenantConfiguration tenantConfiguration = tenant.getTenantConfiguration(); - params.put(INSTANCE_NAME, StringUtils.defaultIfEmpty(tenantConfiguration.getInstanceName(), "Appsmith")); + return organizationService.getOrganizationConfiguration().map(organization -> { + final OrganizationConfiguration organizationConfiguration = organization.getOrganizationConfiguration(); + params.put( + INSTANCE_NAME, StringUtils.defaultIfEmpty(organizationConfiguration.getInstanceName(), "Appsmith")); return params; }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java index 0a89a9c81fca..3df6f2d0577c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java @@ -2,19 +2,20 @@ import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; -import com.appsmith.server.domains.Tenant; +import com.appsmith.server.domains.Organization; import reactor.core.publisher.Mono; import java.util.Map; public interface FeatureFlagMigrationHelperCE { - Mono> getUpdatedFlagsWithPendingMigration(Tenant defaultTenant); + Mono> getUpdatedFlagsWithPendingMigration( + Organization defaultOrganization); Mono> getUpdatedFlagsWithPendingMigration( - Tenant tenant, boolean forceUpdate); + Organization organization, boolean forceUpdate); - Mono checkAndExecuteMigrationsForFeatureFlag(Tenant tenant, FeatureFlagEnum featureFlagEnum); + Mono checkAndExecuteMigrationsForFeatureFlag(Organization organization, FeatureFlagEnum featureFlagEnum); - Mono executeMigrationsBasedOnFeatureFlag(Tenant tenant, FeatureFlagEnum featureFlagEnum); + Mono executeMigrationsBasedOnFeatureFlag(Organization organization, FeatureFlagEnum featureFlagEnum); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java index 566d2865adf8..df4756817626 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java @@ -2,8 +2,8 @@ import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.services.CacheableFeatureFlagHelper; @@ -32,74 +32,76 @@ public class FeatureFlagMigrationHelperCEImpl implements FeatureFlagMigrationHel /** * To avoid race condition keep the refresh rate lower than cron execution interval {@link ScheduledTaskCEImpl} - * to update the tenant level feature flags + * to update the org level feature flags */ - private static final long TENANT_FEATURES_CACHE_TIME_MIN = 115; + private static final long ORGANIZATION_FEATURES_CACHE_TIME_MIN = 115; @Override - public Mono> getUpdatedFlagsWithPendingMigration(Tenant defaultTenant) { - return getUpdatedFlagsWithPendingMigration(defaultTenant, FALSE); + public Mono> getUpdatedFlagsWithPendingMigration( + Organization defaultOrganization) { + return getUpdatedFlagsWithPendingMigration(defaultOrganization, FALSE); } /** * Method to get the updated feature flags with pending migrations. This method finds and registers the flags for * migration by comparing the diffs between the feature flags stored in cache and the latest one pulled from CS - * @param tenant Tenant for which the feature flags need to be updated - * @param forceUpdate Flag to force update the tenant level feature flags + * @param organization Organization for which the feature flags need to be updated + * @param forceUpdate Flag to force update the organization level feature flags * @return Map of feature flags with pending migrations */ @Override public Mono> getUpdatedFlagsWithPendingMigration( - Tenant tenant, boolean forceUpdate) { + Organization organization, boolean forceUpdate) { /* * 1. Fetch current/saved feature flags from cache - * 2. Force update the tenant flags keeping existing flags as fallback in case the API call to fetch the flags fails for some reason + * 2. Force update the organization flags keeping existing flags as fallback in case the API call to fetch the flags fails for some reason * 3. Get the diff and update the flags with pending migrations to be used to run migrations selectively */ return cacheableFeatureFlagHelper - .fetchCachedTenantFeatures(tenant.getId()) + .fetchCachedOrganizationFeatures(organization.getId()) .zipWhen(existingCachedFlags -> { if (existingCachedFlags.getRefreshedAt().until(Instant.now(), ChronoUnit.MINUTES) - < TENANT_FEATURES_CACHE_TIME_MIN + < ORGANIZATION_FEATURES_CACHE_TIME_MIN && !forceUpdate) { return Mono.just(existingCachedFlags); } - return this.refreshTenantFeatures(tenant, existingCachedFlags); + return this.refreshOrganizationFeatures(organization, existingCachedFlags); }) .map(tuple2 -> { CachedFeatures existingCachedFlags = tuple2.getT1(); CachedFeatures latestFlags = tuple2.getT2(); - return this.getUpdatedFlagsWithPendingMigration(tenant, latestFlags, existingCachedFlags); + return this.getUpdatedFlagsWithPendingMigration(organization, latestFlags, existingCachedFlags); }); } /** - * Method to force update the tenant level feature flags. This will be utilised in scenarios where we don't want + * Method to force update the organization level feature flags. This will be utilised in scenarios where we don't want * to wait for the flags to get updated for cron scheduled time * - * @param tenant tenant for which the feature flags need to be updated + * @param organization organization for which the feature flags need to be updated * @return Cached features */ - private Mono refreshTenantFeatures(Tenant tenant, CachedFeatures existingCachedFeatures) { + private Mono refreshOrganizationFeatures( + Organization organization, CachedFeatures existingCachedFeatures) { /* 1. Force update the flag a. Evict the cache b. Fetch and save latest flags from CS - 2. In case the tenant is unable to fetch the latest flags save the existing flags from step 1 to cache (fallback) + 2. In case the organization is unable to fetch the latest flags save the existing flags from step 1 to cache (fallback) */ - String tenantId = tenant.getId(); + String organizationId = organization.getId(); return cacheableFeatureFlagHelper - .evictCachedTenantFeatures(tenantId) - .then(cacheableFeatureFlagHelper.fetchCachedTenantFeatures(tenantId)) + .evictCachedOrganizationFeatures(organizationId) + .then(cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(organizationId)) .flatMap(features -> { if (CollectionUtils.isNullOrEmpty(features.getFeatures())) { // In case the retrieval of the latest flags from CS encounters an error, the previous flags // will serve as a fallback value. return cacheableFeatureFlagHelper - .evictCachedTenantFeatures(tenantId) - .then(cacheableFeatureFlagHelper.updateCachedTenantFeatures( - tenantId, existingCachedFeatures)); + .evictCachedOrganizationFeatures(organizationId) + .then(cacheableFeatureFlagHelper.updateCachedOrganizationFeatures( + organizationId, existingCachedFeatures)); } return Mono.just(features); }); @@ -121,16 +123,16 @@ private Mono refreshTenantFeatures(Tenant tenant, CachedFeatures * Step 4: User adds the valid key or renews the subscription again which results in enabling the feature and * ends up in nullifying the effect for step 2 * - * @param tenant Tenant for which the feature flag migrations stats needs to be stored + * @param organization Organization for which the feature flag migrations stats needs to be stored * @param latestFlags Latest flags pulled in from CS * @param existingCachedFlags Flags which are already stored in cache - * @return updated tenant with the required flags with pending migrations + * @return updated organization with the required flags with pending migrations */ private Map getUpdatedFlagsWithPendingMigration( - Tenant tenant, CachedFeatures latestFlags, CachedFeatures existingCachedFlags) { + Organization organization, CachedFeatures latestFlags, CachedFeatures existingCachedFlags) { // 1. Check if there are any diffs for the feature flags - // 2. Update the flags for pending migration within provided tenant object + // 2. Update the flags for pending migration within provided organization object Map featureDiffsWithMigrationType = new HashMap<>(); Map existingFeatureMap = existingCachedFlags.getFeatures(); latestFlags.getFeatures().forEach((key, value) -> { @@ -147,16 +149,17 @@ private Map getUpdatedFlagsWithPendingMig } } }); - return getUpdatedFlagsWithPendingMigration(featureDiffsWithMigrationType, tenant); + return getUpdatedFlagsWithPendingMigration(featureDiffsWithMigrationType, organization); } private Map getUpdatedFlagsWithPendingMigration( - Map latestFeatureDiffsWithMigrationType, Tenant dbTenant) { + Map latestFeatureDiffsWithMigrationType, + Organization dbOrganization) { Map featuresWithPendingMigrationDB = - dbTenant.getTenantConfiguration().getFeaturesWithPendingMigration() == null + dbOrganization.getOrganizationConfiguration().getFeaturesWithPendingMigration() == null ? new HashMap<>() - : dbTenant.getTenantConfiguration().getFeaturesWithPendingMigration(); + : dbOrganization.getOrganizationConfiguration().getFeaturesWithPendingMigration(); Map updatedFlagsForMigrations = new HashMap<>(featuresWithPendingMigrationDB); @@ -197,25 +200,26 @@ with disable type (This will happen via cron to check the license status) /** * Method to check and execute if the migrations are required for the provided feature flag. - * @param tenant Tenant for which the migrations need to be executed + * @param organization Organization for which the migrations need to be executed * @param featureFlagEnum Feature flag for which the migrations need to be executed * @return Boolean indicating if the migrations is successfully executed or not */ - public Mono checkAndExecuteMigrationsForFeatureFlag(Tenant tenant, FeatureFlagEnum featureFlagEnum) { + public Mono checkAndExecuteMigrationsForFeatureFlag( + Organization organization, FeatureFlagEnum featureFlagEnum) { - TenantConfiguration tenantConfiguration = tenant.getTenantConfiguration(); + OrganizationConfiguration organizationConfiguration = organization.getOrganizationConfiguration(); if (featureFlagEnum == null - || tenantConfiguration == null - || CollectionUtils.isNullOrEmpty(tenantConfiguration.getFeaturesWithPendingMigration())) { + || organizationConfiguration == null + || CollectionUtils.isNullOrEmpty(organizationConfiguration.getFeaturesWithPendingMigration())) { return Mono.just(TRUE); } - return isMigrationRequired(tenant, featureFlagEnum).flatMap(isMigrationRequired -> { + return isMigrationRequired(organization, featureFlagEnum).flatMap(isMigrationRequired -> { if (FALSE.equals(isMigrationRequired)) { return Mono.just(TRUE); } Map featuresWithPendingMigration = - tenantConfiguration.getFeaturesWithPendingMigration(); + organizationConfiguration.getFeaturesWithPendingMigration(); if (CollectionUtils.isNullOrEmpty(featuresWithPendingMigration) || !featuresWithPendingMigration.containsKey(featureFlagEnum)) { return Mono.just(TRUE); @@ -224,24 +228,24 @@ public Mono checkAndExecuteMigrationsForFeatureFlag(Tenant tenant, Feat "Running the migration for flag {} with migration type {}", featureFlagEnum.name(), featuresWithPendingMigration.get(featureFlagEnum)); - return this.executeMigrationsBasedOnFeatureFlag(tenant, featureFlagEnum); + return this.executeMigrationsBasedOnFeatureFlag(organization, featureFlagEnum); }); } /** * Method to check if the migrations are required for the provided feature flag. - * @param tenant Tenant for which the migrations need to be executed + * @param organization Organization for which the migrations need to be executed * @param featureFlagEnum Feature flag for which the migrations need to be executed * @return Boolean indicating if the migrations is required or not */ - private Mono isMigrationRequired(Tenant tenant, FeatureFlagEnum featureFlagEnum) { + private Mono isMigrationRequired(Organization organization, FeatureFlagEnum featureFlagEnum) { Map featureMigrationTypeMap = - tenant.getTenantConfiguration().getFeaturesWithPendingMigration(); + organization.getOrganizationConfiguration().getFeaturesWithPendingMigration(); if (CollectionUtils.isNullOrEmpty(featureMigrationTypeMap)) { return Mono.just(FALSE); } return cacheableFeatureFlagHelper - .fetchCachedTenantFeatures(tenant.getId()) + .fetchCachedOrganizationFeatures(organization.getId()) .map(cachedFeatures -> { Map featureFlags = cachedFeatures.getFeatures(); if (featureFlags.containsKey(featureFlagEnum.name())) { @@ -258,12 +262,13 @@ private Mono isMigrationRequired(Tenant tenant, FeatureFlagEnum feature /** * Method to execute the migrations for the given feature flag. - * @param tenant Tenant for which the migrations need to be executed + * @param organization Organization for which the migrations need to be executed * @param featureFlagEnum Feature flag for which the migrations need to be executed * @return Boolean indicating if the migrations is successfully executed or not */ @Override - public Mono executeMigrationsBasedOnFeatureFlag(Tenant tenant, FeatureFlagEnum featureFlagEnum) { + public Mono executeMigrationsBasedOnFeatureFlag( + Organization organization, FeatureFlagEnum featureFlagEnum) { return Mono.just(TRUE); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCE.java index 9d97843468bb..18d5b550246b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCE.java @@ -17,5 +17,5 @@ public interface InstanceConfigHelperCE { Mono checkMongoDBVersion(); - Mono updateCacheForTenantFeatureFlags(); + Mono updateCacheForOrganizationFeatureFlags(); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCEImpl.java index 68126fa0c7da..1d26b253898b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/InstanceConfigHelperCEImpl.java @@ -226,7 +226,7 @@ public Mono checkMongoDBVersion() { } @Override - public Mono updateCacheForTenantFeatureFlags() { - return featureFlagService.getTenantFeatures().then(); + public Mono updateCacheForOrganizationFeatureFlags() { + return featureFlagService.getOrganizationFeatures().then(); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java index eea297afe722..b927e4f6d7ad 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java @@ -91,7 +91,7 @@ public Mono makeSuperUser(List users) { .then(Mono.just(users)) .flatMapMany(Flux::fromIterable) .flatMap(user -> permissionGroupRepository.evictAllPermissionGroupCachesForUser( - user.getEmail(), user.getTenantId())) + user.getEmail(), user.getOrganizationId())) .then(Mono.just(Boolean.TRUE)); } @@ -110,7 +110,7 @@ public Mono removeSuperUser(List users) { .then(Mono.just(users)) .flatMapMany(Flux::fromIterable) .flatMap(user -> permissionGroupRepository.evictAllPermissionGroupCachesForUser( - user.getEmail(), user.getTenantId())) + user.getEmail(), user.getOrganizationId())) .then(Mono.just(Boolean.TRUE)); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java index 7c66c89061a1..5cff3aae357a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java @@ -31,13 +31,9 @@ public interface ImportServiceCE { ArtifactBasedImportService getArtifactBasedImportService(ArtifactType artifactType); - /** - * This method takes a file part and makes a Json entity which implements the ArtifactExchangeJson interface - * - * @param filePart : filePart from which the contents would be made - * @return : Json entity which implements ArtifactExchangeJson - */ - Mono extractArtifactExchangeJson(Part filePart); + Mono readFilePartToString(Part file); + + Mono extractArtifactExchangeJson(String jsonString); /** * Hydrates an Artifact within the specified workspace by saving the provided JSON file. @@ -50,6 +46,17 @@ public interface ImportServiceCE { Mono extractArtifactExchangeJsonAndSaveArtifact( Part filePart, String workspaceId, String artifactId); + /** + * Hydrates an Artifact within the specified workspace by saving the provided JSON file. + * + * @param jsonContents The JSON representing the Artifact object to be saved. + * The Artifact implements the Artifact interface. + * @param workspaceId The identifier for the destination workspace. + * @param artifactId + */ + Mono extractArtifactExchangeJsonAndSaveArtifact( + String jsonContents, String workspaceId, String artifactId); + /** * Saves the provided ArtifactExchangeJson within the specified workspace. * diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java index 66a3d8c73e4c..696aa38b0ef2 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java @@ -100,50 +100,61 @@ public class ImportServiceCEImpl implements ImportServiceCE { }; } - /** - * This method takes a file part and makes a Json entity which implements the ArtifactExchangeJson interface - * - * @param filePart : filePart from which the contents would be made - * @return : Json entity which implements ArtifactExchangeJson - */ - public Mono extractArtifactExchangeJson(Part filePart) { - - final MediaType contentType = filePart.headers().getContentType(); + @Override + public Mono readFilePartToString(Part file) { + final MediaType contentType = file.headers().getContentType(); if (contentType == null || !ALLOWED_CONTENT_TYPES.contains(contentType)) { log.error("Invalid content type, {}", contentType); return Mono.error(new AppsmithException(AppsmithError.VALIDATION_FAILURE, INVALID_JSON_FILE)); } - return DataBufferUtils.join(filePart.content()) - .map(dataBuffer -> { - byte[] data = new byte[dataBuffer.readableByteCount()]; - dataBuffer.read(data); - DataBufferUtils.release(dataBuffer); - return new String(data); - }) - .map(jsonString -> { - gsonBuilder.registerTypeAdapter(ArtifactExchangeJson.class, artifactExchangeJsonAdapter); - Gson gson = gsonBuilder.create(); - return gson.fromJson(jsonString, ArtifactExchangeJson.class); - }); + return DataBufferUtils.join(file.content()).map(dataBuffer -> { + byte[] data = new byte[dataBuffer.readableByteCount()]; + dataBuffer.read(data); + DataBufferUtils.release(dataBuffer); + return new String(data); + }); + } + + /** + * This method takes JSON content and makes a JSON entity which implements the ArtifactExchangeJson interface. + * + * @param jsonString JSON string to parse + * @return JSON entity which implements ArtifactExchangeJson + */ + @Override + public Mono extractArtifactExchangeJson(String jsonString) { + return Mono.fromCallable(() -> { + gsonBuilder.registerTypeAdapter(ArtifactExchangeJson.class, artifactExchangeJsonAdapter); + Gson gson = gsonBuilder.create(); + return gson.fromJson(jsonString, ArtifactExchangeJson.class); + }); + } + + @Override + public Mono extractArtifactExchangeJsonAndSaveArtifact( + Part filePart, String workspaceId, String artifactId) { + return readFilePartToString(filePart) + .flatMap(jsonContents -> + extractArtifactExchangeJsonAndSaveArtifact(jsonContents, workspaceId, artifactId)); } /** * Hydrates an Artifact within the specified workspace by saving the provided JSON file. * - * @param filePart The filePart representing the Artifact object to be saved. + * @param jsonContents The jsonContents representing the Artifact object to be saved. * The Artifact implements the Artifact interface. * @param workspaceId The identifier for the destination workspace. */ @Override public Mono extractArtifactExchangeJsonAndSaveArtifact( - Part filePart, String workspaceId, String artifactId) { + String jsonContents, String workspaceId, String artifactId) { if (StringUtils.isEmpty(workspaceId)) { return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.WORKSPACE_ID)); } - Mono importedContextMono = extractArtifactExchangeJson(filePart) + Mono importedContextMono = extractArtifactExchangeJson(jsonContents) .zipWhen(contextJson -> { if (StringUtils.isEmpty(artifactId)) { return importNewArtifactInWorkspaceFromJson(workspaceId, contextJson); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCE.java index b7daf9cedd84..547059d466f3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCE.java @@ -8,8 +8,10 @@ public interface PartialImportServiceCE { + Mono importResourceInPage(String workspaceId, String applicationId, String pageId, Part file); + Mono importResourceInPage( - String workspaceId, String applicationId, String pageId, String branchName, Part file); + String workspaceId, String applicationId, String pageId, String fileContents); Mono importBuildingBlock(BuildingBlockDTO buildingBlockDTO); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCEImpl.java index 7cdca44ee288..181068f83a73 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCEImpl.java @@ -6,7 +6,6 @@ import com.appsmith.external.models.CreatorContextType; import com.appsmith.external.models.Datasource; import com.appsmith.server.acl.AclPermission; -import com.appsmith.server.actioncollections.base.ActionCollectionService; import com.appsmith.server.applications.base.ApplicationService; import com.appsmith.server.constants.FieldName; import com.appsmith.server.datasources.base.DatasourceService; @@ -98,7 +97,6 @@ public class PartialImportServiceCEImpl implements PartialImportServiceCE { private final WidgetRefactorUtil widgetRefactorUtil; private final ApplicationPageService applicationPageService; private final NewActionService newActionService; - private final ActionCollectionService actionCollectionService; private final ArtifactBasedImportService applicationImportService; private final DatasourceService datasourceService; @@ -106,12 +104,19 @@ public class PartialImportServiceCEImpl implements PartialImportServiceCE { private final UpdateLayoutService updateLayoutService; private final DryOperationRepository dryOperationRepository; + @Override + public Mono importResourceInPage(String workspaceId, String applicationId, String pageId, Part file) { + return importService + .readFilePartToString(file) + .flatMap(fileContents -> importResourceInPage(workspaceId, applicationId, pageId, fileContents)); + } + @Override public Mono importResourceInPage( - String workspaceId, String applicationId, String pageId, String branchName, Part file) { + String workspaceId, String applicationId, String pageId, String fileContents) { Mono currUserMono = sessionUserService.getCurrentUser(); return importService - .extractArtifactExchangeJson(file) + .extractArtifactExchangeJson(fileContents) .flatMap(artifactExchangeJson -> { if (artifactExchangeJson instanceof ApplicationJson && isImportableResource((ApplicationJson) artifactExchangeJson)) { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceImpl.java index ae9e89e9a81b..727558d49007 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceImpl.java @@ -1,7 +1,6 @@ package com.appsmith.server.imports.internal.partial; import com.appsmith.external.models.Datasource; -import com.appsmith.server.actioncollections.base.ActionCollectionService; import com.appsmith.server.applications.base.ApplicationService; import com.appsmith.server.datasources.base.DatasourceService; import com.appsmith.server.domains.ActionCollection; @@ -67,7 +66,6 @@ public PartialImportServiceImpl( WidgetRefactorUtil widgetRefactorUtil, ApplicationPageService applicationPageService, NewActionService newActionService, - ActionCollectionService actionCollectionService, ArtifactBasedImportService applicationImportService, DatasourceService datasourceService, CustomJSLibService customJSLibService, @@ -98,7 +96,6 @@ public PartialImportServiceImpl( widgetRefactorUtil, applicationPageService, newActionService, - actionCollectionService, applicationImportService, datasourceService, customJSLibService, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/jslibs/exportable/CustomJSLibExportableServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/jslibs/exportable/CustomJSLibExportableServiceCEImpl.java index 8df63d51380b..bae0aa11ac1e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/jslibs/exportable/CustomJSLibExportableServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/jslibs/exportable/CustomJSLibExportableServiceCEImpl.java @@ -1,6 +1,7 @@ package com.appsmith.server.jslibs.exportable; import com.appsmith.external.git.models.GitResourceType; +import com.appsmith.git.files.FileUtilsImpl; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.Artifact; @@ -78,11 +79,16 @@ public Mono getExportableEntities( artifactExchangeJson .getModifiedResources() .putResource(FieldName.CUSTOM_JS_LIB_LIST, updatedCustomJSLibSet); + + Set updatedCustomJsLibResourceIdentifiers = updatedCustomJSLibSet.stream() + .map(FileUtilsImpl::getJsLibFileName) + .collect(Collectors.toSet()); + artifactExchangeJson .getModifiedResources() .getModifiedResourceIdentifiers() .get(GitResourceType.JSLIB_CONFIG) - .addAll(updatedCustomJSLibSet); + .addAll(updatedCustomJsLibResourceIdentifiers); /** * Previously it was a Set and as Set is an unordered collection of elements that diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java index ba30d97b5614..bfd58c438d5b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java @@ -25,7 +25,6 @@ import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.Permission; -import com.appsmith.server.helpers.TextUtils; import com.appsmith.server.migrations.solutions.UpdateSuperUserMigrationHelper; import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.solutions.PolicySolution; @@ -62,15 +61,12 @@ import static com.appsmith.server.acl.AclPermission.READ_PERMISSION_GROUP_MEMBERS; import static com.appsmith.server.acl.AclPermission.READ_THEMES; import static com.appsmith.server.acl.AppsmithRole.TENANT_ADMIN; -import static com.appsmith.server.constants.EnvVariables.APPSMITH_ADMIN_EMAILS; import static com.appsmith.server.constants.FieldName.DEFAULT_PERMISSION_GROUP; import static com.appsmith.server.constants.FieldName.PERMISSION_GROUP_ID; -import static com.appsmith.server.helpers.CollectionUtils.findSymmetricDiff; import static com.appsmith.server.migrations.DatabaseChangelog1.dropIndexIfExists; import static com.appsmith.server.migrations.DatabaseChangelog1.ensureIndexes; import static com.appsmith.server.migrations.DatabaseChangelog1.installPluginToAllWorkspaces; import static com.appsmith.server.migrations.DatabaseChangelog1.makeIndex; -import static com.appsmith.server.migrations.MigrationHelperMethods.evictPermissionCacheForUsers; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; import static org.springframework.data.mongodb.core.query.Update.update; @@ -443,65 +439,6 @@ public static void doAddPermissionGroupIndex(MongoTemplate mongoTemplate) { ensureIndexes(mongoTemplate, PermissionGroup.class, assignedToUserIds_deleted_compound_index); } - /** - * Changing the order of this function to 10000 so that it always gets executed at the end. - * This ensures that any permission changes for super users happen once all other migrations are completed - */ - @ChangeSet(order = "10000", id = "update-super-users", author = "", runAlways = true) - public void updateSuperUsers( - MongoTemplate mongoTemplate, - CacheableRepositoryHelper cacheableRepositoryHelper, - PolicySolution policySolution, - PolicyGenerator policyGenerator) { - // Read the admin emails from the environment and update the super users accordingly - String adminEmailsStr = System.getenv(String.valueOf(APPSMITH_ADMIN_EMAILS)); - - Set adminEmails = TextUtils.csvToSet(adminEmailsStr); - - Query instanceConfigurationQuery = new Query(); - instanceConfigurationQuery.addCriteria(where(Config.Fields.name).is(FieldName.INSTANCE_CONFIG)); - Config instanceAdminConfiguration = mongoTemplate.findOne(instanceConfigurationQuery, Config.class); - - String instanceAdminPermissionGroupId = - (String) instanceAdminConfiguration.getConfig().get(DEFAULT_PERMISSION_GROUP); - - Query permissionGroupQuery = new Query(); - permissionGroupQuery - .addCriteria(where(PermissionGroup.Fields.id).is(instanceAdminPermissionGroupId)) - .fields() - .include(PermissionGroup.Fields.assignedToUserIds); - PermissionGroup instanceAdminPG = mongoTemplate.findOne(permissionGroupQuery, PermissionGroup.class); - - Query tenantQuery = new Query(); - tenantQuery.addCriteria(where(Tenant.Fields.slug).is("default")); - Tenant tenant = mongoTemplate.findOne(tenantQuery, Tenant.class); - - Set userIds = adminEmails.stream() - .map(email -> email.trim()) - .map(String::toLowerCase) - .map(email -> { - Query userQuery = new Query(); - userQuery.addCriteria(where(User.Fields.email).is(email)); - User user = mongoTemplate.findOne(userQuery, User.class); - - if (user == null) { - log.info("Creating super user with username {}", email); - user = updateSuperUserMigrationHelper.createNewUser( - email, tenant, instanceAdminPG, mongoTemplate, policySolution, policyGenerator); - } - - return user.getId(); - }) - .collect(Collectors.toSet()); - - Set oldSuperUsers = instanceAdminPG.getAssignedToUserIds(); - Set updatedUserIds = findSymmetricDiff(oldSuperUsers, userIds); - evictPermissionCacheForUsers(updatedUserIds, mongoTemplate, cacheableRepositoryHelper); - - Update update = new Update().set(PermissionGroup.Fields.assignedToUserIds, userIds); - mongoTemplate.updateFirst(permissionGroupQuery, update, PermissionGroup.class); - } - @ChangeSet(order = "034", id = "update-bad-theme-state", author = "") public void updateBadThemeState( MongoTemplate mongoTemplate, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/MigrationHelperMethods.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/MigrationHelperMethods.java index 277a3ac5768e..c361a99812cd 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/MigrationHelperMethods.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/MigrationHelperMethods.java @@ -224,7 +224,7 @@ public static void evictPermissionCacheForUsers( if (user != null) { // blocking call for cache eviction to ensure its subscribed immediately before proceeding further. cacheableRepositoryHelper - .evictPermissionGroupsUser(user.getEmail(), user.getTenantId()) + .evictPermissionGroupsUser(user.getEmail(), user.getOrganizationId()) .block(); } }); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration059PolicySetToPolicyMap.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration059PolicySetToPolicyMap.java index 76c3f6d00ac5..501414f0d527 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration059PolicySetToPolicyMap.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration059PolicySetToPolicyMap.java @@ -91,7 +91,13 @@ public void execute() { tenantQuery.addCriteria(where(Tenant.Fields.slug).is(DEFAULT)); Tenant defaultTenant = mongoTemplate.findOne(tenantQuery, Tenant.class).block(); assert defaultTenant != null : "Default tenant not found"; - cacheableRepositoryHelper.evictCachedTenant(defaultTenant.getId()).block(); + + // The following code line has been commented as part of Tenant to Organization migration. The function does not + // exist + // anymore and no need to evict the cached tenant anymore because Migration 065 would migrate the tenant to + // organization + // and a new cache line would be set for the organization. + // cacheableRepositoryHelper.evictCachedTenant(defaultTenant.getId()).block(); } private static Mono executeForCollection(ReactiveMongoTemplate mongoTemplate, String collectionName) { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration061TenantPolicySetToPolicyMap.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration061TenantPolicySetToPolicyMap.java index cb966fd6b810..592f39090790 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration061TenantPolicySetToPolicyMap.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration061TenantPolicySetToPolicyMap.java @@ -49,7 +49,13 @@ public void executeMigration() { defaultTenant.getPolicies().forEach(policy -> policyMap.put(policy.getPermission(), policy)); defaultTenant.setPolicyMap(policyMap); mongoTemplate.save(defaultTenant); - cacheableRepositoryHelper.evictCachedTenant(defaultTenant.getId()).block(); + + // The following code line has been commented as part of Tenant to Organization migration. The function does + // not exist + // anymore and no need to evict the cached tenant anymore because Migration 065 would migrate the tenant to + // organization + // and a new cache line would be set for the organization. + // cacheableRepositoryHelper.evictCachedTenant(defaultTenant.getId()).block(); } else { log.info( "Tenant already has policyMap set. Skipping migration to update policy set to map in tenant Migration061TenantPolicySetToPolicyMap."); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration065_CopyTenantIdToOrganizationId.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration065_CopyTenantIdToOrganizationId.java new file mode 100644 index 000000000000..77aee8777311 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration065_CopyTenantIdToOrganizationId.java @@ -0,0 +1,245 @@ +package com.appsmith.server.migrations.db.ce; + +import com.appsmith.external.models.Policy; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.PermissionGroup; +import com.appsmith.server.domains.UsagePulse; +import com.appsmith.server.domains.User; +import com.appsmith.server.domains.Workspace; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.mongodb.DuplicateKeyException; +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; +import lombok.extern.slf4j.Slf4j; +import org.bson.Document; +import org.bson.types.ObjectId; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.redis.core.ReactiveRedisOperations; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.springframework.data.mongodb.core.query.Criteria.where; + +@Slf4j +@ChangeUnit(id = "copy-tenant-id-to-organization-id", order = "065") +public class Migration065_CopyTenantIdToOrganizationId { + + private final ReactiveRedisOperations reactiveRedisOperations; + private final ObjectMapper objectMapper; + private final MongoTemplate mongoTemplate; + + private final List> DOMAIN_CLASSES = + Arrays.asList(User.class, Workspace.class, PermissionGroup.class, UsagePulse.class); + + public Migration065_CopyTenantIdToOrganizationId( + @Qualifier("reactiveRedisOperations") ReactiveRedisOperations reactiveRedisOperations, + ObjectMapper objectMapper, + MongoTemplate mongoTemplate) { + this.reactiveRedisOperations = reactiveRedisOperations; + this.objectMapper = objectMapper; + this.mongoTemplate = mongoTemplate; + } + + @RollbackExecution + public void rollbackExecution() {} + + @Execution + public void execute() { + migrateTenantCollection(); + migrateMongoCollections(); + + // Removing this for environments where the migration hasn't run yet since for k8 clusters with default + // configurations, the redis session migration is taking longer than startup probe (which is 2 minutes). + // migrateRedisData(); + } + + private void migrateTenantCollection() { + try { + // Get the single tenant document + Document tenant = mongoTemplate.findOne(new Query(), Document.class, "tenant"); + + if (tenant == null) { + log.info("No tenant found to migrate"); + return; + } + + try { + // Create new organization document + Document organizationDocument = new Document(); + + // Copy all fields from tenant to organization + organizationDocument.putAll(tenant); + + // Ensure the _id is preserved + String tenantId = tenant.getObjectId("_id").toString(); + organizationDocument.put("_id", new ObjectId(tenantId)); + + // Handle configuration key rename + if (tenant.containsKey("tenantConfiguration")) { + organizationDocument.put("organizationConfiguration", tenant.get("tenantConfiguration")); + organizationDocument.remove("tenantConfiguration"); + } + + Organization organization = mongoTemplate.getConverter().read(Organization.class, organizationDocument); + + Map existingPolicyMap = organization.getPolicyMap(); + if (existingPolicyMap == null || existingPolicyMap.isEmpty()) { + return; + } + + Map updatedPolicyMap = new HashMap<>(existingPolicyMap); // Copy existing policies + Set updatedPolicies = + new HashSet<>(organization.getPolicies()); // Copy existing deprecated policies + + // Process each policy + for (Map.Entry entry : existingPolicyMap.entrySet()) { + Policy existingPolicy = entry.getValue(); + String permission = existingPolicy.getPermission(); + + // Only process policies that contain 'tenant' + if (permission.toLowerCase().contains("tenant")) { + // Create new policy with 'organization' instead of 'tenant' + String newPermission = permission.replaceAll("(?i)tenant", "organization"); + + // Skip if the new permission already exists + if (!updatedPolicyMap.containsKey(newPermission)) { + // Create a new policy object with the same permissions but new name + Policy newPolicy = + new Policy(newPermission, new HashSet<>(existingPolicy.getPermissionGroups())); + + updatedPolicyMap.put(newPermission, newPolicy); + updatedPolicies.add(newPolicy); + } + } + } + + organization.setPolicyMap(updatedPolicyMap); + organization.setPolicies(updatedPolicies); + + // Insert into organization collection + try { + mongoTemplate.save(organization); + log.info("Successfully migrated tenant to organization with id: {}", tenantId); + } catch (DuplicateKeyException e) { + log.warn("Organization already exists for tenant: {}", tenantId); + } + + } catch (Exception e) { + log.error("Error migrating tenant: {}", tenant.get("_id"), e); + } + + } catch (Exception e) { + log.error("Error during tenant to organization migration", e); + } + } + + private void migrateMongoCollections() { + for (Class domainClass : DOMAIN_CLASSES) { + try { + migrateCollection(domainClass); + } catch (Exception e) { + log.error("Error while migrating collection for {}: ", domainClass.getSimpleName(), e); + } + } + } + + private void migrateCollection(Class domainClass) { + Query query = + new Query(where("tenantId").exists(true).and("organizationId").exists(false)); + + // Create an update pipeline that copies the value + List pipeline = Arrays.asList(new Document("$set", new Document("organizationId", "$tenantId"))); + + try { + long updatedCount = mongoTemplate + .getCollection(mongoTemplate.getCollectionName(domainClass)) + .updateMany(query.getQueryObject(), pipeline) + .getModifiedCount(); + + log.info( + "Successfully copied tenantId to organizationId for {} documents in collection: {}", + updatedCount, + domainClass.getSimpleName()); + } catch (Exception e) { + log.error( + "Error while copying tenantId to organizationId for collection {}: ", + domainClass.getSimpleName(), + e); + throw e; + } + } + + private void migrateRedisData() { + try { + // Get all session keys + List sessionKeys = reactiveRedisOperations + .keys("spring:session:sessions:*") + .collectList() + .block(); + + if (sessionKeys == null || sessionKeys.isEmpty()) { + log.info("No session keys found in Redis"); + return; + } + + int updatedCount = 0; + for (String sessionKey : sessionKeys) { + Map sessionData = reactiveRedisOperations + .opsForHash() + .entries(sessionKey) + .collectMap(entry -> entry.getKey(), entry -> entry.getValue()) + .block(); + + if (sessionData != null && sessionData.containsKey("sessionAttr:SPRING_SECURITY_CONTEXT")) { + try { + String sessionStr = sessionData + .get("sessionAttr:SPRING_SECURITY_CONTEXT") + .toString(); + // Extract the appsmith-session JSON string + if (sessionStr.contains("appsmith-session:")) { + String jsonStr = + sessionStr.substring(sessionStr.indexOf('{'), sessionStr.lastIndexOf('}') + 1); + JsonNode jsonNode = objectMapper.readTree(jsonStr); + ObjectNode objectNode = (ObjectNode) jsonNode; + + if (objectNode.has("tenantId") && !objectNode.has("organizationId")) { + // Copy tenantId value to organizationId + objectNode.put( + "organizationId", + objectNode.get("tenantId").asText()); + // Remove tenantId + objectNode.remove("tenantId"); + + // Reconstruct the session string with updated JSON + String updatedJson = objectMapper.writeValueAsString(objectNode); + String updatedSessionStr = "appsmith-session:" + updatedJson; + + // Convert to byte array if needed + reactiveRedisOperations + .opsForHash() + .put(sessionKey, "sessionAttr:SPRING_SECURITY_CONTEXT", updatedSessionStr) + .block(); + updatedCount++; + } + } + } catch (Exception e) { + log.error("Error processing Redis session key {}: ", sessionKey, e); + } + } + } + log.info("Successfully migrated {} Redis sessions", updatedCount); + } catch (Exception e) { + log.error("Error while migrating Redis session data: ", e); + } + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration066_CacheBustTenantOrgMigration.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration066_CacheBustTenantOrgMigration.java new file mode 100644 index 000000000000..295b5bf23213 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration066_CacheBustTenantOrgMigration.java @@ -0,0 +1,58 @@ +package com.appsmith.server.migrations.db.ce; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.ReactiveRedisOperations; +import org.springframework.data.redis.core.ScanOptions; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicInteger; + +@Slf4j +@ChangeUnit(order = "066", id = "cache-bust-tenant-org-migration") +public class Migration066_CacheBustTenantOrgMigration { + @RollbackExecution + public void rollbackExecution() {} + + @Execution + public void execute( + @Qualifier("reactiveRedisOperations") ReactiveRedisOperations reactiveRedisOperations) { + log.info("Starting cache bust migration"); + scanForKeysAcrossCluster(reactiveRedisOperations, "*").block(); + log.info("Completed cache bust migration"); + } + + private Mono scanForKeysAcrossCluster( + ReactiveRedisOperations reactiveRedisOperations, String pattern) { + AtomicInteger deletedKeysCount = new AtomicInteger(0); + + return reactiveRedisOperations + .execute(connection -> { + Flux scanFlux = connection + .keyCommands() + .scan(ScanOptions.scanOptions() + .match(pattern) + .count(1000) + .build()); + + return scanFlux.flatMap(scannedKey -> connection + .keyCommands() + .del(scannedKey) + .doOnSuccess(result -> { + int count = deletedKeysCount.incrementAndGet(); + if (count % 10000 == 0) { + log.info("Processed {} Redis keys", count); + } + })) + .then() + .doOnSuccess(v -> log.info("Total Redis keys processed: {}", deletedKeysCount.get())) + .doOnError(error -> log.error("Redis key deletion error: {}", error.getMessage())); + }) + .then(); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration10000_UpdateSuperUser.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration10000_UpdateSuperUser.java new file mode 100644 index 000000000000..03cd7e111787 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/db/ce/Migration10000_UpdateSuperUser.java @@ -0,0 +1,113 @@ +package com.appsmith.server.migrations.db.ce; + +import com.appsmith.server.acl.PolicyGenerator; +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Config; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.PermissionGroup; +import com.appsmith.server.domains.User; +import com.appsmith.server.helpers.TextUtils; +import com.appsmith.server.migrations.solutions.UpdateSuperUserMigrationHelper; +import com.appsmith.server.repositories.CacheableRepositoryHelper; +import com.appsmith.server.solutions.PolicySolution; +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; + +import java.util.Set; +import java.util.stream.Collectors; + +import static com.appsmith.server.constants.EnvVariables.APPSMITH_ADMIN_EMAILS; +import static com.appsmith.server.constants.ce.FieldNameCE.DEFAULT_PERMISSION_GROUP; +import static com.appsmith.server.helpers.CollectionUtils.findSymmetricDiff; +import static com.appsmith.server.migrations.MigrationHelperMethods.evictPermissionCacheForUsers; +import static org.springframework.data.mongodb.core.query.Criteria.where; + +/** + * The order of this migration is set to 10000 so that it always gets executed at the end. + * This ensures that any permission changes for super users happen once all other migrations are completed. + */ +@Slf4j +@ChangeUnit(order = "10000", id = "update-super-users", author = "", runAlways = true) +public class Migration10000_UpdateSuperUser { + + private final MongoTemplate mongoTemplate; + private final CacheableRepositoryHelper cacheableRepositoryHelper; + private final PolicySolution policySolution; + private final PolicyGenerator policyGenerator; + private final UpdateSuperUserMigrationHelper updateSuperUserMigrationHelper; + + public Migration10000_UpdateSuperUser( + MongoTemplate mongoTemplate, + CacheableRepositoryHelper cacheableRepositoryHelper, + PolicySolution policySolution, + PolicyGenerator policyGenerator) { + this.mongoTemplate = mongoTemplate; + this.cacheableRepositoryHelper = cacheableRepositoryHelper; + this.policySolution = policySolution; + this.policyGenerator = policyGenerator; + this.updateSuperUserMigrationHelper = new UpdateSuperUserMigrationHelper(); + } + + @RollbackExecution + public void rollbackExecution() {} + + @Execution + public void executeMigration() { + // Read the admin emails from the environment and update the super users accordingly + String adminEmailsStr = System.getenv(String.valueOf(APPSMITH_ADMIN_EMAILS)); + + Set adminEmails = TextUtils.csvToSet(adminEmailsStr); + + Query instanceConfigurationQuery = new Query(); + instanceConfigurationQuery.addCriteria(where(Config.Fields.name).is(FieldName.INSTANCE_CONFIG)); + Config instanceAdminConfiguration = mongoTemplate.findOne(instanceConfigurationQuery, Config.class); + + String instanceAdminPermissionGroupId = + (String) instanceAdminConfiguration.getConfig().get(DEFAULT_PERMISSION_GROUP); + + Query permissionGroupQuery = new Query(); + permissionGroupQuery + .addCriteria(where(PermissionGroup.Fields.id).is(instanceAdminPermissionGroupId)) + .fields() + .include(PermissionGroup.Fields.assignedToUserIds); + PermissionGroup instanceAdminPG = mongoTemplate.findOne(permissionGroupQuery, PermissionGroup.class); + + Query organizationQuery = new Query(); + organizationQuery.addCriteria(where(Organization.Fields.slug).is("default")); + Organization organization = mongoTemplate.findOne(organizationQuery, Organization.class); + + Set userIds = adminEmails.stream() + .map(email -> email.trim()) + .map(String::toLowerCase) + .map(email -> { + Query userQuery = new Query(); + userQuery.addCriteria(where(User.Fields.email).is(email)); + User user = mongoTemplate.findOne(userQuery, User.class); + + if (user == null) { + log.info("Creating super user with username {}", email); + user = updateSuperUserMigrationHelper.createNewUser( + email, organization, instanceAdminPG, mongoTemplate, policySolution, policyGenerator); + } + + return user.getId(); + }) + .collect(Collectors.toSet()); + + Set oldSuperUsers = instanceAdminPG.getAssignedToUserIds(); + Set updatedUserIds = findSymmetricDiff(oldSuperUsers, userIds); + evictPermissionCacheForUsers(updatedUserIds, mongoTemplate, cacheableRepositoryHelper); + + Update update = new Update().set(PermissionGroup.Fields.assignedToUserIds, userIds); + mongoTemplate.updateFirst(permissionGroupQuery, update, PermissionGroup.class); + + // Assign all super users to the default role + updateSuperUserMigrationHelper.assignAllSuperUsersToDefaultRole( + userIds, mongoTemplate, cacheableRepositoryHelper); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/solutions/ce/UpdateSuperUserMigrationHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/solutions/ce/UpdateSuperUserMigrationHelperCE.java index 0c9836a18c2e..8c45a7c4d0fc 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/solutions/ce/UpdateSuperUserMigrationHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/solutions/ce/UpdateSuperUserMigrationHelperCE.java @@ -3,10 +3,11 @@ import com.appsmith.external.models.Policy; import com.appsmith.server.acl.PolicyGenerator; import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.PermissionGroup; -import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.User; import com.appsmith.server.dtos.Permission; +import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.solutions.PolicySolution; import org.jetbrains.annotations.NotNull; import org.springframework.data.mongodb.core.MongoTemplate; @@ -24,7 +25,7 @@ protected Set generateUserPolicy( User user, PermissionGroup userManagementRole, PermissionGroup instanceAdminRole, - Tenant tenant, + Organization organization, PolicySolution policySolution, PolicyGenerator policyGenerator) { Policy readUserPolicy = Policy.builder() @@ -45,7 +46,7 @@ protected Set generateUserPolicy( public User createNewUser( String email, - Tenant tenant, + Organization organization, PermissionGroup instanceAdminRole, MongoTemplate mongoTemplate, PolicySolution policySolution, @@ -53,14 +54,14 @@ public User createNewUser( User user = new User(); user.setEmail(email); user.setIsEnabled(false); - user.setTenantId(tenant.getId()); + user.setOrganizationId(organization.getId()); user.setCreatedAt(Instant.now()); user = mongoTemplate.save(user); PermissionGroup userManagementPermissionGroup = createUserManagementPermissionGroup(mongoTemplate, user); Set userPolicies = this.generateUserPolicy( - user, userManagementPermissionGroup, instanceAdminRole, tenant, policySolution, policyGenerator); + user, userManagementPermissionGroup, instanceAdminRole, organization, policySolution, policyGenerator); user.setPolicies(userPolicies); @@ -79,4 +80,9 @@ public User createNewUser( PermissionGroup savedPermissionGroup = mongoTemplate.save(userManagementPermissionGroup); return savedPermissionGroup; } + + public void assignAllSuperUsersToDefaultRole( + Set userIds, MongoTemplate mongoTemplate, CacheableRepositoryHelper cacheableRepositoryHelper) { + // Empty function in CE to override in EE + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java index a983e279d1eb..bfa29a1b8b75 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java @@ -10,7 +10,7 @@ import com.appsmith.server.repositories.PluginRepository; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.solutions.DatasourceTriggerSolution; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpHeaders; @@ -28,7 +28,7 @@ public class PluginTriggerSolutionCEImpl implements PluginTriggerSolutionCE { private final PluginExecutorHelper pluginExecutorHelper; private final PluginRepository pluginRepository; private final ConfigService configService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final FeatureFlagService featureFlagService; public PluginTriggerSolutionCEImpl( @@ -36,13 +36,13 @@ public PluginTriggerSolutionCEImpl( PluginExecutorHelper pluginExecutorHelper, PluginRepository pluginRepository, ConfigService configService, - TenantService tenantService, + OrganizationService organizationService, FeatureFlagService featureFlagService) { this.datasourceTriggerSolution = datasourceTriggerSolution; this.pluginExecutorHelper = pluginExecutorHelper; this.pluginRepository = pluginRepository; this.configService = configService; - this.tenantService = tenantService; + this.organizationService = organizationService; this.featureFlagService = featureFlagService; } @@ -81,7 +81,7 @@ public Mono trigger( // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag // Once thoroughly tested, this flag can be removed Map featureFlagMap = - featureFlagService.getCachedTenantFeatureFlags().getFeatures(); + featureFlagService.getCachedOrganizationFeatureFlags().getFeatures(); /* * Since there is no datasource provided, we are passing the Datasource Context connection and datasourceConfiguration as null. @@ -91,7 +91,7 @@ public Mono trigger( Plugin plugin = pair.getT1(); PluginExecutor pluginExecutor = pair.getT2(); setHeadersToTriggerRequest(plugin, httpHeaders, triggerRequestDTO); - return setTenantAndInstanceId(triggerRequestDTO) + return setOrganizationAndInstanceId(triggerRequestDTO) .flatMap(updatedTriggerRequestDTO -> ((PluginExecutor) pluginExecutor) .triggerWithFlags(null, null, updatedTriggerRequestDTO, featureFlagMap)); }); @@ -115,12 +115,12 @@ public Mono trigger( }); } - private Mono setTenantAndInstanceId(TriggerRequestDTO triggerRequestDTO) { - return tenantService - .getDefaultTenantId() + private Mono setOrganizationAndInstanceId(TriggerRequestDTO triggerRequestDTO) { + return organizationService + .getDefaultOrganizationId() .zipWith(configService.getInstanceId()) .map(tuple -> { - triggerRequestDTO.setTenantId(tuple.getT1()); + triggerRequestDTO.setOrganizationId(tuple.getT1()); triggerRequestDTO.setInstanceId(tuple.getT2()); return triggerRequestDTO; }); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionImpl.java index 373235b5e09d..afc84986419b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionImpl.java @@ -4,7 +4,7 @@ import com.appsmith.server.repositories.PluginRepository; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.solutions.DatasourceTriggerSolution; import org.springframework.stereotype.Component; @@ -15,14 +15,14 @@ public PluginTriggerSolutionImpl( PluginExecutorHelper pluginExecutorHelper, PluginRepository pluginRepository, ConfigService configService, - TenantService tenantService, + OrganizationService organizationService, FeatureFlagService featureFlagService) { super( datasourceTriggerSolution, pluginExecutorHelper, pluginRepository, configService, - tenantService, + organizationService, featureFlagService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomOrganizationRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomOrganizationRepository.java new file mode 100644 index 000000000000..aac5045ce90e --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomOrganizationRepository.java @@ -0,0 +1,5 @@ +package com.appsmith.server.repositories; + +import com.appsmith.server.repositories.ce.CustomOrganizationRepositoryCE; + +public interface CustomOrganizationRepository extends CustomOrganizationRepositoryCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomOrganizationRepositoryImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomOrganizationRepositoryImpl.java new file mode 100644 index 000000000000..0f1a49fe8319 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomOrganizationRepositoryImpl.java @@ -0,0 +1,6 @@ +package com.appsmith.server.repositories; + +import com.appsmith.server.repositories.ce.CustomOrganizationRepositoryCEImpl; + +public class CustomOrganizationRepositoryImpl extends CustomOrganizationRepositoryCEImpl + implements CustomOrganizationRepository {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomTenantRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomTenantRepository.java deleted file mode 100644 index 19002ae711a8..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomTenantRepository.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.appsmith.server.repositories; - -import com.appsmith.server.repositories.ce.CustomTenantRepositoryCE; - -public interface CustomTenantRepository extends CustomTenantRepositoryCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomTenantRepositoryImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomTenantRepositoryImpl.java deleted file mode 100644 index b56a9559f6e4..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomTenantRepositoryImpl.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.appsmith.server.repositories; - -import com.appsmith.server.repositories.ce.CustomTenantRepositoryCEImpl; - -public class CustomTenantRepositoryImpl extends CustomTenantRepositoryCEImpl implements CustomTenantRepository {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/OrganizationRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/OrganizationRepository.java new file mode 100644 index 000000000000..4a9c8f4ecbab --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/OrganizationRepository.java @@ -0,0 +1,7 @@ +package com.appsmith.server.repositories; + +import com.appsmith.server.repositories.ce.OrganizationRepositoryCE; +import org.springframework.stereotype.Repository; + +@Repository +public interface OrganizationRepository extends OrganizationRepositoryCE, CustomOrganizationRepository {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/TenantRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/TenantRepository.java deleted file mode 100644 index 3c138f24e290..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/TenantRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.appsmith.server.repositories; - -import com.appsmith.server.repositories.ce.TenantRepositoryCE; -import org.springframework.stereotype.Repository; - -@Repository -public interface TenantRepository extends TenantRepositoryCE, CustomTenantRepository {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/BaseAppsmithRepositoryCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/BaseAppsmithRepositoryCEImpl.java index 8a297df4bf0e..cb3179a2dcb8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/BaseAppsmithRepositoryCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/BaseAppsmithRepositoryCEImpl.java @@ -446,15 +446,15 @@ public Mono setUserPermissionsInObject(T obj, Set permissionGroups) { protected Mono> getAllPermissionGroupsForUser(User user) { Mono userMono = Mono.just(user); - if (user.getTenantId() == null) { - userMono = cacheableRepositoryHelper.getDefaultTenantId().map(tenantId -> { - user.setTenantId(tenantId); + if (user.getOrganizationId() == null) { + userMono = cacheableRepositoryHelper.getDefaultOrganizationId().map(organizationId -> { + user.setOrganizationId(organizationId); return user; }); } - return userMono.flatMap(userWithTenant -> Mono.zip( - cacheableRepositoryHelper.getPermissionGroupsOfUser(userWithTenant), + return userMono.flatMap(userWithOrganization -> Mono.zip( + cacheableRepositoryHelper.getPermissionGroupsOfUser(userWithOrganization), getAnonymousUserPermissionGroups())) .map(tuple -> { Set permissionGroups = new HashSet<>(tuple.getT1()); @@ -477,9 +477,9 @@ protected Mono> getAllPermissionGroupsForUser(User user) { protected Mono> getStrictPermissionGroupsForUser(User user) { Mono userMono = Mono.just(user); - if (user.getTenantId() == null) { - userMono = cacheableRepositoryHelper.getDefaultTenantId().map(tenantId -> { - user.setTenantId(tenantId); + if (user.getOrganizationId() == null) { + userMono = cacheableRepositoryHelper.getDefaultOrganizationId().map(organizationId -> { + user.setOrganizationId(organizationId); return user; }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java index fc66e5e2eeec..7c6e7e3e007f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java @@ -1,6 +1,6 @@ package com.appsmith.server.repositories.ce; -import com.appsmith.server.domains.Tenant; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.User; import reactor.core.publisher.Mono; @@ -15,15 +15,15 @@ public interface CacheableRepositoryHelperCE { Mono> getPermissionGroupsOfAnonymousUser(); - Mono evictPermissionGroupsUser(String email, String tenantId); + Mono evictPermissionGroupsUser(String email, String organizationId); - Mono getDefaultTenantId(); + Mono getDefaultOrganizationId(); Mono getInstanceAdminPermissionGroupId(); - Mono fetchDefaultTenant(String tenantId); + Mono fetchDefaultOrganization(String organizationId); - Mono evictCachedTenant(String tenantId); + Mono evictCachedOrganization(String organizationId); /** * Retrieves the base application ID from the cache based on the provided base page ID. diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java index 3cdcc4e8b087..d0d67118af77 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java @@ -4,9 +4,9 @@ import com.appsmith.caching.annotations.CacheEvict; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.Config; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.PermissionGroup; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.exceptions.AppsmithError; @@ -29,7 +29,7 @@ import java.util.Set; import java.util.stream.Collectors; -import static com.appsmith.external.constants.spans.TenantSpan.FETCH_TENANT_FROM_DB_SPAN; +import static com.appsmith.external.constants.spans.OrganizationSpan.FETCH_ORGANIZATION_FROM_DB_SPAN; import static com.appsmith.server.constants.FieldName.PERMISSION_GROUP_ID; import static com.appsmith.server.constants.ce.FieldNameCE.ANONYMOUS_USER; import static com.appsmith.server.constants.ce.FieldNameCE.DEFAULT_PERMISSION_GROUP; @@ -45,7 +45,7 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe private final ObservationRegistry observationRegistry; private static final String CACHE_DEFAULT_PAGE_ID_TO_DEFAULT_APPLICATION_ID = "pageIdToAppId"; - @Cache(cacheName = "permissionGroupsForUser", key = "{#user.email + #user.tenantId}") + @Cache(cacheName = "permissionGroupsForUser", key = "{#user.email + #user.organizationId}") @Override public Mono> getPermissionGroupsOfUser(User user) { @@ -127,27 +127,28 @@ public Mono> getPermissionGroupsOfAnonymousUser() { return Mono.error(new AppsmithException(AppsmithError.SERVER_NOT_READY)); } - @CacheEvict(cacheName = "permissionGroupsForUser", key = "{#email + #tenantId}") + @CacheEvict(cacheName = "permissionGroupsForUser", key = "{#email + #organizationId}") @Override - public Mono evictPermissionGroupsUser(String email, String tenantId) { + public Mono evictPermissionGroupsUser(String email, String organizationId) { return Mono.empty(); } @Override - public Mono getDefaultTenantId() { - String defaultTenantId = inMemoryCacheableRepositoryHelper.getDefaultTenantId(); - if (defaultTenantId != null && !defaultTenantId.isEmpty()) { - return Mono.just(defaultTenantId); + public Mono getDefaultOrganizationId() { + String defaultOrganizationId = inMemoryCacheableRepositoryHelper.getDefaultOrganizationId(); + if (defaultOrganizationId != null && !defaultOrganizationId.isEmpty()) { + return Mono.just(defaultOrganizationId); } - BridgeQuery defaultTenantCriteria = Bridge.equal(Tenant.Fields.slug, FieldName.DEFAULT); + BridgeQuery defaultOrganizationCriteria = + Bridge.equal(Organization.Fields.slug, FieldName.DEFAULT); Query query = new Query(); - query.addCriteria(defaultTenantCriteria); + query.addCriteria(defaultOrganizationCriteria); - return mongoOperations.findOne(query, Tenant.class).map(defaultTenant -> { - String newDefaultTenantId = defaultTenant.getId(); - inMemoryCacheableRepositoryHelper.setDefaultTenantId(newDefaultTenantId); - return newDefaultTenantId; + return mongoOperations.findOne(query, Organization.class).map(defaultOrganization -> { + String newDefaultOrganizationId = defaultOrganization.getId(); + inMemoryCacheableRepositoryHelper.setDefaultOrganizationId(newDefaultOrganizationId); + return newDefaultOrganizationId; }); } @@ -171,35 +172,36 @@ public Mono getInstanceAdminPermissionGroupId() { } /** - * Returns the default tenant from the cache if present. - * If not present in cache, then it fetches the default tenant from the database and adds to redis. - * @param tenantId + * Returns the default organization from the cache if present. + * If not present in cache, then it fetches the default organization from the database and adds to redis. + * @param organizationId * @return */ - @Cache(cacheName = "tenant", key = "{#tenantId}") + @Cache(cacheName = "organization", key = "{#organizationId}") @Override - public Mono fetchDefaultTenant(String tenantId) { - BridgeQuery defaultTenantCriteria = Bridge.equal(Tenant.Fields.slug, FieldName.DEFAULT); - BridgeQuery notDeletedCriteria = notDeleted(); - BridgeQuery andCriteria = Bridge.and(defaultTenantCriteria, notDeletedCriteria); + public Mono fetchDefaultOrganization(String organizationId) { + BridgeQuery defaultOrganizationCriteria = + Bridge.equal(Organization.Fields.slug, FieldName.DEFAULT); + BridgeQuery notDeletedCriteria = notDeleted(); + BridgeQuery andCriteria = Bridge.and(defaultOrganizationCriteria, notDeletedCriteria); Query query = new Query(); query.addCriteria(andCriteria); - log.info("Fetching tenant from database as it couldn't be found in the cache!"); + log.info("Fetching organization from database as it couldn't be found in the cache!"); return mongoOperations - .findOne(query, Tenant.class) - .map(tenant -> { - if (tenant.getTenantConfiguration() == null) { - tenant.setTenantConfiguration(new TenantConfiguration()); + .findOne(query, Organization.class) + .map(organization -> { + if (organization.getOrganizationConfiguration() == null) { + organization.setOrganizationConfiguration(new OrganizationConfiguration()); } - return tenant; + return organization; }) - .name(FETCH_TENANT_FROM_DB_SPAN) + .name(FETCH_ORGANIZATION_FROM_DB_SPAN) .tap(Micrometer.observation(observationRegistry)); } - @CacheEvict(cacheName = "tenant", key = "{#tenantId}") + @CacheEvict(cacheName = "organization", key = "{#organizationId}") @Override - public Mono evictCachedTenant(String tenantId) { + public Mono evictCachedOrganization(String organizationId) { return Mono.empty().then(); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomOrganizationRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomOrganizationRepositoryCE.java new file mode 100644 index 000000000000..1f3b9139fb47 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomOrganizationRepositoryCE.java @@ -0,0 +1,6 @@ +package com.appsmith.server.repositories.ce; + +import com.appsmith.server.domains.Organization; +import com.appsmith.server.repositories.AppsmithRepository; + +public interface CustomOrganizationRepositoryCE extends AppsmithRepository {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomOrganizationRepositoryCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomOrganizationRepositoryCEImpl.java new file mode 100644 index 000000000000..7b21660b8509 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomOrganizationRepositoryCEImpl.java @@ -0,0 +1,9 @@ +package com.appsmith.server.repositories.ce; + +import com.appsmith.server.domains.Organization; +import com.appsmith.server.repositories.BaseAppsmithRepositoryImpl; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CustomOrganizationRepositoryCEImpl extends BaseAppsmithRepositoryImpl + implements CustomOrganizationRepositoryCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCE.java index 0dc34109dd43..250c6110ed26 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCE.java @@ -23,9 +23,9 @@ Flux findAllByAssignedToUserIdAndDefaultWorkspaceId( Flux findByDefaultWorkspaceIds(Set workspaceIds, AclPermission permission); - Mono evictPermissionGroupsUser(String email, String tenantId); + Mono evictPermissionGroupsUser(String email, String organizationId); - Mono evictAllPermissionGroupCachesForUser(String email, String tenantId); + Mono evictAllPermissionGroupCachesForUser(String email, String organizationId); Flux findAllByAssignedToUserIn( Set userIds, Optional> includeFields, Optional permission); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCEImpl.java index 19d41817d5fb..95c95c7f92cb 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomPermissionGroupRepositoryCEImpl.java @@ -62,13 +62,13 @@ public Flux findByDefaultWorkspaceIds(Set workspaceIds, } @Override - public Mono evictPermissionGroupsUser(String email, String tenantId) { - return cacheableRepositoryHelper.evictPermissionGroupsUser(email, tenantId); + public Mono evictPermissionGroupsUser(String email, String organizationId) { + return cacheableRepositoryHelper.evictPermissionGroupsUser(email, organizationId); } @Override - public Mono evictAllPermissionGroupCachesForUser(String email, String tenantId) { - return this.evictPermissionGroupsUser(email, tenantId); + public Mono evictAllPermissionGroupCachesForUser(String email, String organizationId) { + return this.evictPermissionGroupsUser(email, organizationId); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomTenantRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomTenantRepositoryCE.java deleted file mode 100644 index e9cc3b92c097..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomTenantRepositoryCE.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.appsmith.server.repositories.ce; - -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.repositories.AppsmithRepository; - -public interface CustomTenantRepositoryCE extends AppsmithRepository {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomTenantRepositoryCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomTenantRepositoryCEImpl.java deleted file mode 100644 index 2b56879bdef8..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomTenantRepositoryCEImpl.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.appsmith.server.repositories.ce; - -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.repositories.BaseAppsmithRepositoryImpl; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class CustomTenantRepositoryCEImpl extends BaseAppsmithRepositoryImpl - implements CustomTenantRepositoryCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCE.java index 10c66781ecf4..856f1c54e152 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCE.java @@ -12,7 +12,7 @@ public interface CustomUserRepositoryCE extends AppsmithRepository { Mono findByEmail(String email, AclPermission aclPermission); - Mono findByEmailAndTenantId(String email, String tenantId); + Mono findByEmailAndOrganizationId(String email, String organizationId); Mono isUsersEmpty(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCEImpl.java index 17db68683223..96e6650ee5b2 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomUserRepositoryCEImpl.java @@ -26,9 +26,9 @@ public Mono findByEmail(String email, AclPermission aclPermission) { } @Override - public Mono findByEmailAndTenantId(String email, String tenantId) { + public Mono findByEmailAndOrganizationId(String email, String organizationId) { return queryBuilder() - .criteria(Bridge.equal(User.Fields.email, email).equal(User.Fields.tenantId, tenantId)) + .criteria(Bridge.equal(User.Fields.email, email).equal(User.Fields.organizationId, organizationId)) .one(); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCE.java index facee3f521de..7216b7443a50 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCE.java @@ -13,7 +13,8 @@ public interface CustomWorkspaceRepositoryCE extends AppsmithRepository findByName(String name, AclPermission aclPermission); - Flux findByIdsIn(Set workspaceIds, String tenantId, AclPermission aclPermission, Sort sort); + Flux findByIdsIn( + Set workspaceIds, String organizationId, AclPermission aclPermission, Sort sort); Flux findAll(AclPermission permission); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCEImpl.java index df76a0a10742..4aa572372e29 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CustomWorkspaceRepositoryCEImpl.java @@ -30,10 +30,10 @@ public Mono findByName(String name, AclPermission aclPermission) { @Override public Flux findByIdsIn( - Set workspaceIds, String tenantId, AclPermission aclPermission, Sort sort) { + Set workspaceIds, String organizationId, AclPermission aclPermission, Sort sort) { return queryBuilder() .criteria(Bridge.in(Workspace.Fields.id, workspaceIds) - .equal(Workspace.Fields.tenantId, tenantId)) + .equal(Workspace.Fields.organizationId, organizationId)) .permission(aclPermission) .sort(sort) .all(); @@ -42,7 +42,7 @@ public Flux findByIdsIn( @Override public Flux findAll(AclPermission permission) { return sessionUserService.getCurrentUser().flatMapMany(user -> queryBuilder() - .criteria(Bridge.equal(Workspace.Fields.tenantId, user.getTenantId())) + .criteria(Bridge.equal(Workspace.Fields.organizationId, user.getOrganizationId())) .permission(permission) .all()); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/OrganizationRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/OrganizationRepositoryCE.java new file mode 100644 index 000000000000..de74acb700ff --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/OrganizationRepositoryCE.java @@ -0,0 +1,11 @@ +package com.appsmith.server.repositories.ce; + +import com.appsmith.server.domains.Organization; +import com.appsmith.server.repositories.BaseRepository; +import reactor.core.publisher.Mono; + +public interface OrganizationRepositoryCE extends BaseRepository, CustomOrganizationRepositoryCE { + // Use organizationService.getDefaultOrganization() instead of this method as it is cached to redis. + @Deprecated(forRemoval = true) + Mono findBySlug(String slug); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/TenantRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/TenantRepositoryCE.java deleted file mode 100644 index 7cad8f0f12a4..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/TenantRepositoryCE.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.appsmith.server.repositories.ce; - -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.repositories.BaseRepository; -import reactor.core.publisher.Mono; - -public interface TenantRepositoryCE extends BaseRepository, CustomTenantRepositoryCE { - // Use tenantService.getDefaultTenant() instead of this method as it is cached to redis. - @Deprecated(forRemoval = true) - Mono findBySlug(String slug); -} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/UserRepositoryCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/UserRepositoryCE.java index ac0b365f3210..17895ce93f08 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/UserRepositoryCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/UserRepositoryCE.java @@ -29,5 +29,5 @@ public interface UserRepositoryCE extends BaseRepository, CustomUs Mono countByDeletedAtIsNullAndLastActiveAtGreaterThanAndIsSystemGeneratedIsNot( Instant lastActiveAt, Boolean excludeSystemGenerated); - Mono findByEmailAndTenantId(String email, String tenantId); + Mono findByEmailAndOrganizationId(String email, String organizationId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CacheableFeatureFlagHelperImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CacheableFeatureFlagHelperImpl.java index abd2394cdf69..54b06ec8c2b8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CacheableFeatureFlagHelperImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CacheableFeatureFlagHelperImpl.java @@ -2,7 +2,7 @@ import com.appsmith.server.configurations.CloudServicesConfig; import com.appsmith.server.configurations.CommonConfig; -import com.appsmith.server.repositories.TenantRepository; +import com.appsmith.server.repositories.OrganizationRepository; import com.appsmith.server.services.ce.CacheableFeatureFlagHelperCEImpl; import com.appsmith.server.solutions.ReleaseNotesService; import lombok.extern.slf4j.Slf4j; @@ -13,14 +13,14 @@ public class CacheableFeatureFlagHelperImpl extends CacheableFeatureFlagHelperCEImpl implements CacheableFeatureFlagHelper { public CacheableFeatureFlagHelperImpl( - TenantRepository tenantRepository, + OrganizationRepository organizationRepository, ConfigService configService, CloudServicesConfig cloudServicesConfig, CommonConfig commonConfig, UserIdentifierService userIdentifierService, ReleaseNotesService releaseNotesService) { super( - tenantRepository, + organizationRepository, configService, cloudServicesConfig, commonConfig, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ConsolidatedAPIServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ConsolidatedAPIServiceImpl.java index 649619990d7e..cbf20d6813c2 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ConsolidatedAPIServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ConsolidatedAPIServiceImpl.java @@ -23,7 +23,7 @@ public ConsolidatedAPIServiceImpl( SessionUserService sessionUserService, UserService userService, UserDataService userDataService, - TenantService tenantService, + OrganizationService organizationService, ProductAlertService productAlertService, NewPageService newPageService, NewActionService newActionService, @@ -42,7 +42,7 @@ public ConsolidatedAPIServiceImpl( sessionUserService, userService, userDataService, - tenantService, + organizationService, productAlertService, newPageService, newActionService, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/FeatureFlagServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/FeatureFlagServiceImpl.java index 103a3fd5df97..9423abc9f671 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/FeatureFlagServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/FeatureFlagServiceImpl.java @@ -8,13 +8,13 @@ public class FeatureFlagServiceImpl extends FeatureFlagServiceCEImpl implements FeatureFlagService { public FeatureFlagServiceImpl( SessionUserService sessionUserService, - TenantService tenantService, + OrganizationService organizationService, UserIdentifierService userIdentifierService, CacheableFeatureFlagHelper cacheableFeatureFlagHelper, FeatureFlagMigrationHelper featureFlagMigrationHelper) { super( sessionUserService, - tenantService, + organizationService, userIdentifierService, cacheableFeatureFlagHelper, featureFlagMigrationHelper); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationService.java new file mode 100644 index 000000000000..2e5f7af07a85 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationService.java @@ -0,0 +1,5 @@ +package com.appsmith.server.services; + +import com.appsmith.server.services.ce.OrganizationServiceCE; + +public interface OrganizationService extends OrganizationServiceCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java similarity index 78% rename from app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java rename to app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java index 53fdf6b1be7f..f8c1b46cf21c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java @@ -3,8 +3,8 @@ import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.repositories.CacheableRepositoryHelper; -import com.appsmith.server.repositories.TenantRepository; -import com.appsmith.server.services.ce.TenantServiceCEImpl; +import com.appsmith.server.repositories.OrganizationRepository; +import com.appsmith.server.services.ce.OrganizationServiceCEImpl; import com.appsmith.server.solutions.EnvManager; import io.micrometer.observation.ObservationRegistry; import jakarta.validation.Validator; @@ -12,11 +12,11 @@ import org.springframework.stereotype.Service; @Service -public class TenantServiceImpl extends TenantServiceCEImpl implements TenantService { +public class OrganizationServiceImpl extends OrganizationServiceCEImpl implements OrganizationService { - public TenantServiceImpl( + public OrganizationServiceImpl( Validator validator, - TenantRepository repository, + OrganizationRepository repository, AnalyticsService analyticsService, ConfigService configService, @Lazy EnvManager envManager, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java index 56d0694f5a9f..0df6d95080a4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java @@ -18,7 +18,7 @@ public PermissionGroupServiceImpl( PermissionGroupRepository repository, AnalyticsService analyticsService, SessionUserService sessionUserService, - TenantService tenantService, + OrganizationService organizationService, UserRepository userRepository, PolicySolution policySolution, ConfigRepository configRepository, @@ -29,7 +29,7 @@ public PermissionGroupServiceImpl( repository, analyticsService, sessionUserService, - tenantService, + organizationService, userRepository, policySolution, configRepository, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantService.java deleted file mode 100644 index 30b371afa49e..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/TenantService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.appsmith.server.services; - -import com.appsmith.server.services.ce.TenantServiceCE; - -public interface TenantService extends TenantServiceCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UsagePulseServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UsagePulseServiceImpl.java index f20294f9a1ba..3ac0ad266642 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UsagePulseServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UsagePulseServiceImpl.java @@ -12,9 +12,9 @@ public UsagePulseServiceImpl( UsagePulseRepository repository, SessionUserService sessionUserService, UserService userService, - TenantService tenantService, + OrganizationService organizationService, ConfigService configService, CommonConfig commonConfig) { - super(repository, sessionUserService, userService, tenantService, configService, commonConfig); + super(repository, sessionUserService, userService, organizationService, configService, commonConfig); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserDataServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserDataServiceImpl.java index 1b1d5fb61967..030c6cc69f29 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserDataServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserDataServiceImpl.java @@ -21,7 +21,7 @@ public UserDataServiceImpl( ReleaseNotesService releaseNotesService, FeatureFlagService featureFlagService, ApplicationRepository applicationRepository, - TenantService tenantService) { + OrganizationService organizationService) { super( validator, @@ -33,6 +33,6 @@ public UserDataServiceImpl( releaseNotesService, featureFlagService, applicationRepository, - tenantService); + organizationService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java index bed86dbc475f..0f0b98bde6c2 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java @@ -35,7 +35,7 @@ public UserServiceImpl( CommonConfig commonConfig, EmailConfig emailConfig, UserDataService userDataService, - TenantService tenantService, + OrganizationService organizationService, PermissionGroupService permissionGroupService, UserUtils userUtils, EmailVerificationTokenRepository emailVerificationTokenRepository, @@ -53,7 +53,7 @@ public UserServiceImpl( passwordEncoder, commonConfig, userDataService, - tenantService, + organizationService, userUtils, emailVerificationTokenRepository, emailService, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserWorkspaceServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserWorkspaceServiceImpl.java index 487a58508e67..f3ed33931c6f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserWorkspaceServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserWorkspaceServiceImpl.java @@ -17,7 +17,7 @@ public UserWorkspaceServiceImpl( UserRepository userRepository, UserDataService userDataService, PermissionGroupService permissionGroupService, - TenantService tenantService, + OrganizationService organizationService, WorkspacePermission workspacePermission, PermissionGroupPermission permissionGroupPermission) { @@ -27,7 +27,7 @@ public UserWorkspaceServiceImpl( userRepository, userDataService, permissionGroupService, - tenantService, + organizationService, workspacePermission, permissionGroupPermission); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCE.java index ab1f5c756ac7..e6c1c04c33b1 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCE.java @@ -16,25 +16,25 @@ public interface CacheableFeatureFlagHelperCE { Mono evictUserCachedFlags(String userIdentifier); /** - * To fetch the tenant new features via cache - * @param tenantId Id of the tenant + * To fetch the org new features via cache + * @param organizationId Id of the organization * @return Mono of CachedFeatures */ - Mono fetchCachedTenantFeatures(String tenantId); + Mono fetchCachedOrganizationFeatures(String organizationId); - Mono updateCachedTenantFeatures(String tenantId, CachedFeatures cachedFeatures); + Mono updateCachedOrganizationFeatures(String organizationId, CachedFeatures cachedFeatures); /** - * To evict the tenant new features cache - * @param tenantId Id of the tenant + * To evict the org new features cache + * @param organizationId Id of the organization * @return Mono of Void */ - Mono evictCachedTenantFeatures(String tenantId); + Mono evictCachedOrganizationFeatures(String organizationId); /** - * To get all tenant features from Cloud Services + * To get all organization features from Cloud Services * @param featuresRequestDTO FeaturesRequestDTO * @return Mono of Map */ - Mono getRemoteFeaturesForTenant(FeaturesRequestDTO featuresRequestDTO); + Mono getRemoteFeaturesForOrganization(FeaturesRequestDTO featuresRequestDTO); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCEImpl.java index 12cc4cafcc0e..07088910c5b3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/CacheableFeatureFlagHelperCEImpl.java @@ -4,7 +4,7 @@ import com.appsmith.caching.annotations.CacheEvict; import com.appsmith.server.configurations.CloudServicesConfig; import com.appsmith.server.configurations.CommonConfig; -import com.appsmith.server.domains.Tenant; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.User; import com.appsmith.server.dtos.FeaturesRequestDTO; import com.appsmith.server.dtos.FeaturesResponseDTO; @@ -16,7 +16,7 @@ import com.appsmith.server.featureflags.FeatureFlagIdentityTraits; import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.helpers.SignatureVerifier; -import com.appsmith.server.repositories.TenantRepository; +import com.appsmith.server.repositories.OrganizationRepository; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.UserIdentifierService; import com.appsmith.server.solutions.ReleaseNotesService; @@ -44,7 +44,7 @@ @Slf4j @RequiredArgsConstructor public class CacheableFeatureFlagHelperCEImpl implements CacheableFeatureFlagHelperCE { - private final TenantRepository tenantRepository; + private final OrganizationRepository organizationRepository; private final ConfigService configService; private final CloudServicesConfig cloudServicesConfig; private final CommonConfig commonConfig; @@ -88,7 +88,7 @@ private Mono> getUserDefaultTraits(User user) { } userTraits.put("email", emailTrait); userTraits.put("instanceId", instanceId); - userTraits.put("tenantId", user.getTenantId()); + userTraits.put("organizationId", user.getOrganizationId()); userTraits.put("emailDomain", emailDomain); userTraits.put("isTelemetryOn", !commonConfig.isTelemetryDisabled()); // for anonymous user, user.getCreatedAt() is null @@ -109,14 +109,14 @@ public Mono evictUserCachedFlags(String userIdentifier) { private Mono> forceAllRemoteFeatureFlagsForUser(String userIdentifier, User user) { Mono instanceIdMono = configService.getInstanceId(); - // TODO: Convert to current tenant when the feature is enabled - Mono defaultTenantMono = tenantRepository.findBySlug(DEFAULT); - return Mono.zip(instanceIdMono, defaultTenantMono, getUserDefaultTraits(user)) + // TODO: Convert to current organization when the feature is enabled + Mono organizationMono = organizationRepository.findBySlug(DEFAULT); + return Mono.zip(instanceIdMono, organizationMono, getUserDefaultTraits(user)) .flatMap(objects -> { - String tenantId = objects.getT2().getId(); + String organizationId = objects.getT2().getId(); String appsmithVersion = releaseNotesService.getRunningVersion(); FeatureFlagIdentityTraits featureFlagIdentityTraits = new FeatureFlagIdentityTraits( - objects.getT1(), tenantId, Set.of(userIdentifier), objects.getT3(), appsmithVersion); + objects.getT1(), organizationId, Set.of(userIdentifier), objects.getT3(), appsmithVersion); return this.getRemoteFeatureFlagsByIdentity(featureFlagIdentityTraits); }) .map(newValue -> ObjectUtils.defaultIfNull(newValue.get(userIdentifier), Map.of())); @@ -162,14 +162,14 @@ private Mono>> getRemoteFeatureFlagsByIdentity( } /** - * To fetch the tenant new features via cache - * @param tenantId Id of the tenant + * To fetch the organization new features via cache + * @param organizationId Id of the organization * @return Mono of CachedFeatures */ - @Cache(cacheName = "tenantNewFeatures", key = "{#tenantId}") + @Cache(cacheName = "organizationNewFeatures", key = "{#organizationId}") @Override - public Mono fetchCachedTenantFeatures(String tenantId) { - return this.forceAllRemoteFeaturesForTenant(tenantId).flatMap(flags -> { + public Mono fetchCachedOrganizationFeatures(String organizationId) { + return this.forceAllRemoteFeaturesForOrganization(organizationId).flatMap(flags -> { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(flags); // If CS is down we expect the empty flags, from upstream method. Hence, setting the refreshed at to past @@ -183,54 +183,54 @@ public Mono fetchCachedTenantFeatures(String tenantId) { }); } - @Cache(cacheName = "tenantNewFeatures", key = "{#tenantId}") + @Cache(cacheName = "organizationNewFeatures", key = "{#organizationId}") @Override - public Mono updateCachedTenantFeatures(String tenantId, CachedFeatures cachedFeatures) { - log.debug("Updating cached tenant features for tenant: {}", tenantId); + public Mono updateCachedOrganizationFeatures(String organizationId, CachedFeatures cachedFeatures) { + log.debug("Updating cached organization features for organization: {}", organizationId); return Mono.just(cachedFeatures); } /** - * To evict the tenant new features cache - * @param tenantId Id of the tenant + * To evict the organization new features cache + * @param organizationId Id of the organization * @return Mono of Void */ - @CacheEvict(cacheName = "tenantNewFeatures", key = "{#tenantId}") + @CacheEvict(cacheName = "organizationNewFeatures", key = "{#organizationId}") @Override - public Mono evictCachedTenantFeatures(String tenantId) { + public Mono evictCachedOrganizationFeatures(String organizationId) { return Mono.empty(); } /** - * To force fetch all tenant features from Cloud Services - * @param tenantId Id of the tenant + * To force fetch all organization features from Cloud Services + * @param organizationId Id of the organization * @return Mono of Map */ - private Mono> forceAllRemoteFeaturesForTenant(String tenantId) { + private Mono> forceAllRemoteFeaturesForOrganization(String organizationId) { Mono instanceIdMono = configService.getInstanceId(); String appsmithVersion = releaseNotesService.getRunningVersion(); return instanceIdMono .map(instanceId -> { FeaturesRequestDTO featuresRequestDTO = new FeaturesRequestDTO(); - featuresRequestDTO.setTenantId(tenantId); + featuresRequestDTO.setOrganizationId(organizationId); featuresRequestDTO.setInstanceId(instanceId); featuresRequestDTO.setAppsmithVersion(appsmithVersion); featuresRequestDTO.setIsCloudHosting(commonConfig.isCloudHosting()); return featuresRequestDTO; }) - .flatMap(this::getRemoteFeaturesForTenant) + .flatMap(this::getRemoteFeaturesForOrganization) .map(responseDTO -> CollectionUtils.isNullOrEmpty(responseDTO.getFeatures()) ? new HashMap<>() : responseDTO.getFeatures()); } /** - * To get all tenant features from Cloud Services. + * To get all organization features from Cloud Services. * @param featuresRequestDTO FeaturesRequestDTO * @return Mono of Map */ @Override - public Mono getRemoteFeaturesForTenant(FeaturesRequestDTO featuresRequestDTO) { + public Mono getRemoteFeaturesForOrganization(FeaturesRequestDTO featuresRequestDTO) { Mono>> responseEntityMono = WebClientUtils.create( cloudServicesConfig.getBaseUrlWithSignatureVerification()) .post() diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java index 97588fb631cb..4f2e12d7e51a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceCEImpl.java @@ -27,9 +27,9 @@ import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.MockDataService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.ProductAlertService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import com.appsmith.server.themes.base.ThemeService; @@ -79,11 +79,11 @@ import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.FEATURE_FLAG_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.FORM_CONFIG_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.MOCK_DATASOURCES_SPAN; +import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.ORGANIZATION_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.PAGES_DSL_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.PAGES_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.PLUGINS_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.PRODUCT_ALERT_SPAN; -import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.TENANT_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.THEMES_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.USER_PROFILE_SPAN; import static com.appsmith.external.constants.spans.ConsolidatedApiSpanNames.WORKSPACE_SPAN; @@ -104,7 +104,7 @@ public class ConsolidatedAPIServiceCEImpl implements ConsolidatedAPIServiceCE { private final SessionUserService sessionUserService; private final UserService userService; private final UserDataService userDataService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final ProductAlertService productAlertService; private final NewPageService newPageService; private final NewActionService newActionService; @@ -121,7 +121,7 @@ public class ConsolidatedAPIServiceCEImpl implements ConsolidatedAPIServiceCE { private final ObservationHelper observationHelper; protected ResponseDTO getSuccessResponse(T data) { - return new ResponseDTO<>(HttpStatus.OK.value(), data, null); + return new ResponseDTO<>(HttpStatus.OK, data); } protected Mono> getErrorResponseMono(Throwable error) { @@ -198,13 +198,13 @@ protected List> getAllFetchableMonos( .cache(); fetches.add(featureFlagsForCurrentUserResponseDTOMonoCache); - /* Get tenant config data */ - fetches.add(tenantService - .getTenantConfiguration() + /* Get organization config data */ + fetches.add(organizationService + .getOrganizationConfiguration() .as(this::toResponseDTO) - .doOnError(e -> log.error("Error fetching tenant config", e)) - .doOnSuccess(consolidatedAPIResponseDTO::setTenantConfig) - .name(getQualifiedSpanName(TENANT_SPAN, mode)) + .doOnError(e -> log.error("Error fetching organization config", e)) + .doOnSuccess(consolidatedAPIResponseDTO::setOrganizationConfig) + .name(getQualifiedSpanName(ORGANIZATION_SPAN, mode)) .tap(Micrometer.observation(observationRegistry))); /* Get any product alert info */ @@ -687,7 +687,7 @@ private boolean isPossibleToCreateQueryWithoutDatasource(Plugin plugin) { Map consolidateAPISignature = Map.of( "userProfile", consolidatedAPIResponseDTO.getUserProfile(), "featureFlags", consolidatedAPIResponseDTO.getFeatureFlags(), - "tenantConfig", consolidatedAPIResponseDTO.getTenantConfig(), + "organizationConfig", consolidatedAPIResponseDTO.getOrganizationConfig(), "productAlert", consolidatedAPIResponseDTO.getProductAlert(), "currentTheme", currentTheme, "themes", themes, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java index c10ba8c38352..3613e452b664 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java @@ -1,7 +1,7 @@ package com.appsmith.server.services.ce; import com.appsmith.external.enums.FeatureFlagEnum; -import com.appsmith.server.domains.Tenant; +import com.appsmith.server.domains.Organization; import com.appsmith.server.featureflags.CachedFeatures; import reactor.core.publisher.Mono; @@ -26,18 +26,18 @@ public interface FeatureFlagServiceCE { Mono> getAllFeatureFlagsForUser(); /** - * To get all features of the tenant from Cloud Services and store them locally + * To get all features of the organization from Cloud Services and store them locally * @return Mono of Void */ - Mono getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations(); + Mono getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations(); /** - * To get all features of the current tenant. + * To get all features of the current organization. * @return Mono of Map */ - Mono> getTenantFeatures(); + Mono> getOrganizationFeatures(); - Mono checkAndExecuteMigrationsForTenantFeatureFlags(Tenant tenant); + Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization); - CachedFeatures getCachedTenantFeatureFlags(); + CachedFeatures getCachedOrganizationFeatureFlags(); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java index fda8d2da3764..7f3a8f4a52d0 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java @@ -2,16 +2,16 @@ import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.MigrationStatus; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.featureflags.CachedFlags; import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.services.CacheableFeatureFlagHelper; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserIdentifierService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -29,7 +29,7 @@ public class FeatureFlagServiceCEImpl implements FeatureFlagServiceCE { private final SessionUserService sessionUserService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final UserIdentifierService userIdentifierService; @@ -38,11 +38,11 @@ public class FeatureFlagServiceCEImpl implements FeatureFlagServiceCE { private final FeatureFlagMigrationHelper featureFlagMigrationHelper; private static final long FEATURE_FLAG_CACHE_TIME_MIN = 120; - private CachedFeatures cachedTenantFeatureFlags; + private CachedFeatures cachedOrganizationFeatureFlags; /** * This function checks if the feature is enabled for the current user. In case the user object is not present, - * i.e. when the method is getting called internally via cron or other mechanism check for tenant level flag and + * i.e. when the method is getting called internally via cron or other mechanism check for organization level flag and * provide a fallback as falsy value i.e. not supported * * @param featureEnum feature flag to be checked @@ -59,20 +59,20 @@ public Mono check(FeatureFlagEnum featureEnum) { /** * Retrieves a map of feature flags along with their corresponding boolean values for the current user. - * This takes into account for both user-level and tenant-level feature flags + * This takes into account for both user-level and organization-level feature flags * * @return A Mono emitting a Map where keys are feature names and values are corresponding boolean flags. */ @Override public Mono> getAllFeatureFlagsForUser() { - // Combine local flags, remote flags, and tenant features, and merge them into a single map - return Mono.zip(this.getAllRemoteFeatureFlagsForUser(), this.getTenantFeatures()) - .map(remoteAndTenantFlags -> { + // Combine local flags, remote flags, and organization features, and merge them into a single map + return Mono.zip(this.getAllRemoteFeatureFlagsForUser(), this.getOrganizationFeatures()) + .map(remoteAndOrganizationFlags -> { Map combinedFlags = new HashMap<>(); - combinedFlags.putAll(remoteAndTenantFlags.getT1()); - // Always add the tenant level flags after the user flags to make sure tenant flags gets the - // precedence - combinedFlags.putAll(remoteAndTenantFlags.getT2()); + combinedFlags.putAll(remoteAndOrganizationFlags.getT1()); + // Always add the organization level flags after the user flags to make sure organization flags gets + // the precedence + combinedFlags.putAll(remoteAndOrganizationFlags.getT2()); return combinedFlags; }); } @@ -115,52 +115,55 @@ private Mono> getAllRemoteFeatureFlagsForUser() { } /** - * To get all features of the tenant from Cloud Services and store them locally + * To get all features of the organization from Cloud Services and store them locally * @return Mono of Void */ - public Mono getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations() { - return tenantService - .getDefaultTenant() - .flatMap(defaultTenant -> + public Mono getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations() { + return organizationService + .getDefaultOrganization() + .flatMap(defaultOrganization -> // 1. Fetch current/saved feature flags from cache - // 2. Force update the tenant flags keeping existing flags as fallback in case the API + // 2. Force update the org flags keeping existing flags as fallback in case the API // call to fetch the flags fails for some reason // 3. Get the diff and update the flags with pending migrations to be used to run // migrations selectively featureFlagMigrationHelper - .getUpdatedFlagsWithPendingMigration(defaultTenant) + .getUpdatedFlagsWithPendingMigration(defaultOrganization) .flatMap(featureFlagWithPendingMigrations -> { - TenantConfiguration tenantConfig = defaultTenant.getTenantConfiguration() == null - ? new TenantConfiguration() - : defaultTenant.getTenantConfiguration(); + OrganizationConfiguration organizationConfiguration = + defaultOrganization.getOrganizationConfiguration() == null + ? new OrganizationConfiguration() + : defaultOrganization.getOrganizationConfiguration(); // We expect the featureFlagWithPendingMigrations to be empty hence // verifying only for null if (featureFlagWithPendingMigrations != null && !featureFlagWithPendingMigrations.equals( - tenantConfig.getFeaturesWithPendingMigration())) { - tenantConfig.setFeaturesWithPendingMigration(featureFlagWithPendingMigrations); + organizationConfiguration.getFeaturesWithPendingMigration())) { + organizationConfiguration.setFeaturesWithPendingMigration( + featureFlagWithPendingMigrations); if (!featureFlagWithPendingMigrations.isEmpty()) { - tenantConfig.setMigrationStatus(MigrationStatus.PENDING); + organizationConfiguration.setMigrationStatus(MigrationStatus.PENDING); } else { - tenantConfig.setMigrationStatus(MigrationStatus.COMPLETED); + organizationConfiguration.setMigrationStatus(MigrationStatus.COMPLETED); } - return tenantService.update(defaultTenant.getId(), defaultTenant); + return organizationService.update( + defaultOrganization.getId(), defaultOrganization); } - return Mono.just(defaultTenant); + return Mono.just(defaultOrganization); })) .then(); } /** - * To get all features of the current tenant. + * To get all features of the current organization. * @return Mono of Map */ - public Mono> getTenantFeatures() { - return tenantService - .getDefaultTenantId() - .flatMap(cacheableFeatureFlagHelper::fetchCachedTenantFeatures) + public Mono> getOrganizationFeatures() { + return organizationService + .getDefaultOrganizationId() + .flatMap(cacheableFeatureFlagHelper::fetchCachedOrganizationFeatures) .map(cachedFeatures -> { - cachedTenantFeatureFlags = cachedFeatures; + cachedOrganizationFeatureFlags = cachedFeatures; return cachedFeatures.getFeatures(); }) .switchIfEmpty(Mono.just(new HashMap<>())); @@ -168,16 +171,15 @@ public Mono> getTenantFeatures() { /** * This function checks if there are any pending migrations for a feature flag and executes them. - * @param tenant tenant for which the migrations need to be executed - * @return tenant with migrations executed + * @param organization organization for which the migrations need to be executed + * @return organization with migrations executed */ @Override - public Mono checkAndExecuteMigrationsForTenantFeatureFlags(Tenant tenant) { - return tenantService.checkAndExecuteMigrationsForTenantFeatureFlags(tenant); + public Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization) { + return organizationService.checkAndExecuteMigrationsForOrganizationFeatureFlags(organization); } - @Override - public CachedFeatures getCachedTenantFeatureFlags() { - return this.cachedTenantFeatureFlags; + public CachedFeatures getCachedOrganizationFeatureFlags() { + return this.cachedOrganizationFeatureFlags; } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/OrganizationServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/OrganizationServiceCE.java new file mode 100644 index 000000000000..d2ecea72254a --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/OrganizationServiceCE.java @@ -0,0 +1,33 @@ +package com.appsmith.server.services.ce; + +import com.appsmith.server.acl.AclPermission; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; +import com.appsmith.server.services.CrudService; +import reactor.core.publisher.Mono; + +public interface OrganizationServiceCE extends CrudService { + + Mono getDefaultOrganizationId(); + + Mono updateOrganizationConfiguration( + String organizationId, OrganizationConfiguration organizationConfiguration); + + Mono findById(String organizationId, AclPermission permission); + + Mono getOrganizationConfiguration(Mono dbOrganizationMono); + + Mono getOrganizationConfiguration(); + + Mono getDefaultOrganization(); + + Mono updateDefaultOrganizationConfiguration(OrganizationConfiguration organizationConfiguration); + + Mono save(Organization organization); + + Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization); + + Mono retrieveById(String id); + + Mono restartOrganization(); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/OrganizationServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/OrganizationServiceCEImpl.java new file mode 100644 index 000000000000..997be981e3e1 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/OrganizationServiceCEImpl.java @@ -0,0 +1,359 @@ +package com.appsmith.server.services.ce; + +import com.appsmith.external.enums.FeatureFlagEnum; +import com.appsmith.external.helpers.AppsmithBeanUtils; +import com.appsmith.server.acl.AclPermission; +import com.appsmith.server.configurations.CommonConfig; +import com.appsmith.server.constants.FeatureMigrationType; +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.constants.MigrationStatus; +import com.appsmith.server.constants.ce.FieldNameCE; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.CollectionUtils; +import com.appsmith.server.helpers.FeatureFlagMigrationHelper; +import com.appsmith.server.repositories.CacheableRepositoryHelper; +import com.appsmith.server.repositories.OrganizationRepository; +import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.BaseService; +import com.appsmith.server.services.ConfigService; +import com.appsmith.server.solutions.EnvManager; +import io.micrometer.observation.ObservationRegistry; +import jakarta.validation.Validator; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.util.StringUtils; +import reactor.core.observability.micrometer.Micrometer; +import reactor.core.publisher.Mono; + +import java.util.Map; + +import static com.appsmith.external.constants.spans.OrganizationSpan.FETCH_DEFAULT_ORGANIZATION_SPAN; +import static com.appsmith.external.constants.spans.OrganizationSpan.FETCH_ORGANIZATION_CACHE_POST_DESERIALIZATION_ERROR_SPAN; +import static com.appsmith.server.acl.AclPermission.MANAGE_ORGANIZATION; +import static java.lang.Boolean.TRUE; + +@Slf4j +public class OrganizationServiceCEImpl extends BaseService + implements OrganizationServiceCE { + + private String organizationId = null; + + private final ConfigService configService; + + private final EnvManager envManager; + + private final FeatureFlagMigrationHelper featureFlagMigrationHelper; + + private final CacheableRepositoryHelper cacheableRepositoryHelper; + + private final CommonConfig commonConfig; + private final ObservationRegistry observationRegistry; + + public OrganizationServiceCEImpl( + Validator validator, + OrganizationRepository repository, + AnalyticsService analyticsService, + ConfigService configService, + @Lazy EnvManager envManager, + FeatureFlagMigrationHelper featureFlagMigrationHelper, + CacheableRepositoryHelper cacheableRepositoryHelper, + CommonConfig commonConfig, + ObservationRegistry observationRegistry) { + super(validator, repository, analyticsService); + this.configService = configService; + this.envManager = envManager; + this.featureFlagMigrationHelper = featureFlagMigrationHelper; + this.cacheableRepositoryHelper = cacheableRepositoryHelper; + this.commonConfig = commonConfig; + this.observationRegistry = observationRegistry; + } + + @Override + public Mono getDefaultOrganizationId() { + + // If the value exists in cache, return it as is + if (StringUtils.hasLength(organizationId)) { + return Mono.just(organizationId); + } + return repository.findBySlug(FieldName.DEFAULT).map(Organization::getId).map(organizationId -> { + // Set the cache value before returning. + this.organizationId = organizationId; + return organizationId; + }); + } + + @Override + public Mono updateOrganizationConfiguration( + String organizationId, OrganizationConfiguration organizationConfiguration) { + Mono evictOrganizationCache = cacheableRepositoryHelper.evictCachedOrganization(organizationId); + return repository + .findById(organizationId, MANAGE_ORGANIZATION) + .switchIfEmpty(Mono.error(new AppsmithException( + AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.ORGANIZATION, organizationId))) + .flatMap(organization -> { + OrganizationConfiguration oldOrganizationConfiguration = + organization.getOrganizationConfiguration(); + if (oldOrganizationConfiguration == null) { + oldOrganizationConfiguration = new OrganizationConfiguration(); + } + Mono> envMono = Mono.empty(); + // instance admin is setting the email verification to true but the SMTP settings are not configured + if (organizationConfiguration.isEmailVerificationEnabled() == Boolean.TRUE) { + envMono = envManager.getAllNonEmpty().flatMap(properties -> { + String mailHost = properties.get("APPSMITH_MAIL_HOST"); + if (mailHost == null || mailHost == "") { + return Mono.error(new AppsmithException(AppsmithError.INVALID_SMTP_CONFIGURATION)); + } + return Mono.empty(); + }); + } + + return envMono.then(Mono.zip(Mono.just(oldOrganizationConfiguration), Mono.just(organization))); + }) + .flatMap(tuple2 -> { + Organization organization = tuple2.getT2(); + OrganizationConfiguration oldConfig = tuple2.getT1(); + AppsmithBeanUtils.copyNestedNonNullProperties(organizationConfiguration, oldConfig); + organization.setOrganizationConfiguration(oldConfig); + Mono updatedOrganizationMono = repository + .updateById(organizationId, organization, MANAGE_ORGANIZATION) + .cache(); + // Firstly updating the Organization object in the database and then evicting the cache. + // returning the updatedOrganization, notice the updatedOrganizationMono is cached using .cache() + // hence it will not be evaluated again + return updatedOrganizationMono + .then(Mono.defer(() -> evictOrganizationCache)) + .then(updatedOrganizationMono); + }); + } + + @Override + public Mono findById(String organizationId, AclPermission permission) { + return repository + .findById(organizationId, permission) + .switchIfEmpty(Mono.error(new AppsmithException( + AppsmithError.NO_RESOURCE_FOUND, FieldNameCE.ORGANIZATION_ID, organizationId))); + } + + @Override + public Mono getOrganizationConfiguration(Mono dbOrganizationMono) { + String adminEmailDomainHash = commonConfig.getAdminEmailDomainHash(); + Mono clientOrganizationMono = configService + .getInstanceId() + .map(instanceId -> { + final Organization organization = new Organization(); + organization.setInstanceId(instanceId); + organization.setAdminEmailDomainHash(adminEmailDomainHash); + + final OrganizationConfiguration config = new OrganizationConfiguration(); + organization.setOrganizationConfiguration(config); + + config.setGoogleMapsKey(System.getenv("APPSMITH_GOOGLE_MAPS_API_KEY")); + + if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"))) { + config.addThirdPartyAuth("google"); + } + + if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GITHUB_CLIENT_ID"))) { + config.addThirdPartyAuth("github"); + } + + config.setIsFormLoginEnabled(!"true".equals(System.getenv("APPSMITH_FORM_LOGIN_DISABLED"))); + + return organization; + }); + + return Mono.zip(dbOrganizationMono, clientOrganizationMono).flatMap(tuple -> { + Organization dbOrganization = tuple.getT1(); + Organization clientOrganization = tuple.getT2(); + return getClientPertinentOrganization(dbOrganization, clientOrganization); + }); + } + + /* + * For now, returning just the instance-id, with an empty organizationConfiguration object in this class. Will enhance + * this function once we start saving other pertinent environment variables in the organization collection. + */ + @Override + public Mono getOrganizationConfiguration() { + Mono dbOrganizationMono = getDefaultOrganization(); + return getOrganizationConfiguration(dbOrganizationMono); + } + + @Override + public Mono getDefaultOrganization() { + // Fetching Organization from redis cache + return getDefaultOrganizationId() + .flatMap(organizationId -> cacheableRepositoryHelper.fetchDefaultOrganization(organizationId)) + .name(FETCH_DEFAULT_ORGANIZATION_SPAN) + .tap(Micrometer.observation(observationRegistry)) + .flatMap(organization -> + repository.setUserPermissionsInObject(organization).switchIfEmpty(Mono.just(organization))) + .onErrorResume(e -> { + e.printStackTrace(); + log.error("Error fetching default organization from redis : {}", e.getMessage()); + // If there is an error fetching the organization from the cache, then evict the cache and fetching + // from the db. This handles the case for deserialization errors. This prevents the entire instance + // to + // go down if organization cache is corrupted. + // More info - https://github.com/appsmithorg/appsmith/issues/33504 + log.info("Evicting the default organization from cache and fetching from the database!"); + return cacheableRepositoryHelper + .evictCachedOrganization(organizationId) + .then(cacheableRepositoryHelper + .fetchDefaultOrganization(organizationId) + .map(organization -> { + if (organization.getOrganizationConfiguration() == null) { + organization.setOrganizationConfiguration(new OrganizationConfiguration()); + } + return organization; + })) + .name(FETCH_ORGANIZATION_CACHE_POST_DESERIALIZATION_ERROR_SPAN) + .tap(Micrometer.observation(observationRegistry)) + .flatMap(organization -> repository + .setUserPermissionsInObject(organization) + .switchIfEmpty(Mono.just(organization))); + }); + } + + @Override + public Mono updateDefaultOrganizationConfiguration( + OrganizationConfiguration organizationConfiguration) { + return getDefaultOrganizationId() + .flatMap(organizationId -> updateOrganizationConfiguration(organizationId, organizationConfiguration)) + .flatMap(updatedOrganization -> getOrganizationConfiguration()); + } + + /** + * To get the Organization with values that are pertinent to the client + * @param dbOrganization Original organization from the database + * @param clientOrganization Organization object that is sent to the client, can be null + * @return Mono + */ + protected Mono getClientPertinentOrganization( + Organization dbOrganization, Organization clientOrganization) { + if (clientOrganization == null) { + clientOrganization = new Organization(); + clientOrganization.setOrganizationConfiguration(new OrganizationConfiguration()); + } + + final OrganizationConfiguration organizationConfiguration = clientOrganization.getOrganizationConfiguration(); + + // Only copy the values that are pertinent to the client + organizationConfiguration.copyNonSensitiveValues(dbOrganization.getOrganizationConfiguration()); + clientOrganization.setUserPermissions(dbOrganization.getUserPermissions()); + + return Mono.just(clientOrganization); + } + + // This function is used to save the organization object in the database and evict the cache + @Override + public Mono save(Organization organization) { + Mono evictCachedOrganization = cacheableRepositoryHelper.evictCachedOrganization(organizationId); + Mono savedOrganizationMono = repository.save(organization).cache(); + return savedOrganizationMono + .then(Mono.defer(() -> evictCachedOrganization)) + .then(savedOrganizationMono); + } + + /** + * This function checks if there are any pending migrations for feature flags and execute them. + * @param organization organization for which the migrations need to be executed + * @return organization with migrations executed + */ + @Override + public Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization) { + if (!isMigrationRequired(organization)) { + return Mono.just(organization); + } + Map featureMigrationTypeMap = + organization.getOrganizationConfiguration().getFeaturesWithPendingMigration(); + + FeatureFlagEnum featureFlagEnum = + featureMigrationTypeMap.keySet().stream().findFirst().orElse(null); + return featureFlagMigrationHelper + .checkAndExecuteMigrationsForFeatureFlag(organization, featureFlagEnum) + .flatMap(isSuccessful -> { + if (TRUE.equals(isSuccessful)) { + featureMigrationTypeMap.remove(featureFlagEnum); + if (CollectionUtils.isNullOrEmpty(featureMigrationTypeMap)) { + organization.getOrganizationConfiguration().setMigrationStatus(MigrationStatus.COMPLETED); + } else { + organization.getOrganizationConfiguration().setMigrationStatus(MigrationStatus.IN_PROGRESS); + } + return this.save(organization) + // Fetch the organization again from DB to make sure the downstream chain is consuming + // the + // latest + // DB object and not the modified one because of the client pertinent changes + .then(repository.findById(organization.getId())) + .flatMap(this::checkAndExecuteMigrationsForOrganizationFeatureFlags); + } + return Mono.error( + new AppsmithException(AppsmithError.FeatureFlagMigrationFailure, featureFlagEnum, "")); + }); + } + + @Override + public Mono retrieveById(String id) { + if (!StringUtils.hasLength(id)) { + return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID)); + } + return repository.findById(id); + } + + /** + * This function updates the organization object in the database and evicts the cache + * @param organizationId + * @param organization + * @return + */ + @Override + public Mono update(String organizationId, Organization organization) { + Mono evictCachedOrganization = cacheableRepositoryHelper.evictCachedOrganization(organizationId); + Mono updatedOrganizationMono = + super.update(organizationId, organization).cache(); + return updatedOrganizationMono + .then(Mono.defer(() -> evictCachedOrganization)) + .then(updatedOrganizationMono); + } + + /** + * This function checks if the organization needs to be restarted and restarts after the feature flag migrations are + * executed. + * + * @return + */ + @Override + public Mono restartOrganization() { + // Avoid dependency on user context as this method will be called internally by the server + Mono defaultOrganizationMono = + this.getDefaultOrganizationId().flatMap(this::retrieveById); + return defaultOrganizationMono.flatMap(updatedOrganization -> { + if (TRUE.equals(updatedOrganization.getOrganizationConfiguration().getIsRestartRequired())) { + log.debug("Triggering organization restart after the feature flag migrations are executed"); + OrganizationConfiguration organizationConfiguration = + updatedOrganization.getOrganizationConfiguration(); + organizationConfiguration.setIsRestartRequired(false); + return this.update(updatedOrganization.getId(), updatedOrganization) + .then(envManager.restartWithoutAclCheck()); + } + return Mono.empty(); + }); + } + + private boolean isMigrationRequired(Organization organization) { + return organization.getOrganizationConfiguration() != null + && (!CollectionUtils.isNullOrEmpty( + organization.getOrganizationConfiguration().getFeaturesWithPendingMigration()) + || (CollectionUtils.isNullOrEmpty(organization + .getOrganizationConfiguration() + .getFeaturesWithPendingMigration()) + && !MigrationStatus.COMPLETED.equals(organization + .getOrganizationConfiguration() + .getMigrationStatus()))); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java index 22e516476ef5..57e0fef46b4e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java @@ -18,8 +18,8 @@ import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.BaseService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.solutions.PermissionGroupPermission; import com.appsmith.server.solutions.PolicySolution; import jakarta.validation.Validator; @@ -45,7 +45,7 @@ public class PermissionGroupServiceCEImpl extends BaseService cleanPermissionGroupCacheForUsers(List userIds) { Mono> userMapMono = userRepository.findAllById(userIds).collectMap(user -> user.getId(), user -> user.getEmail()); - return tenantService - .getDefaultTenantId() + return organizationService + .getDefaultOrganizationId() .zipWith(userMapMono) .flatMapMany(tuple -> { - String defaultTenantId = tuple.getT1(); + String defaultOrganizationId = tuple.getT1(); Map userMap = tuple.getT2(); return Flux.fromIterable(userIds).flatMap(userId -> { String email = userMap.get(userId); return repository - .evictAllPermissionGroupCachesForUser(email, defaultTenantId) + .evictAllPermissionGroupCachesForUser(email, defaultOrganizationId) .thenReturn(TRUE); }); }) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCE.java deleted file mode 100644 index b8fb796bc630..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCE.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.appsmith.server.services.ce; - -import com.appsmith.server.acl.AclPermission; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; -import com.appsmith.server.services.CrudService; -import reactor.core.publisher.Mono; - -public interface TenantServiceCE extends CrudService { - - Mono getDefaultTenantId(); - - Mono updateTenantConfiguration(String tenantId, TenantConfiguration tenantConfiguration); - - Mono findById(String tenantId, AclPermission permission); - - Mono getTenantConfiguration(Mono dbTenantMono); - - Mono getTenantConfiguration(); - - Mono getDefaultTenant(); - - Mono updateDefaultTenantConfiguration(TenantConfiguration tenantConfiguration); - - Mono save(Tenant tenant); - - Mono checkAndExecuteMigrationsForTenantFeatureFlags(Tenant tenant); - - Mono retrieveById(String id); - - Mono restartTenant(); -} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java deleted file mode 100644 index 2592b08a00fe..000000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java +++ /dev/null @@ -1,338 +0,0 @@ -package com.appsmith.server.services.ce; - -import com.appsmith.external.enums.FeatureFlagEnum; -import com.appsmith.external.helpers.AppsmithBeanUtils; -import com.appsmith.server.acl.AclPermission; -import com.appsmith.server.configurations.CommonConfig; -import com.appsmith.server.constants.FeatureMigrationType; -import com.appsmith.server.constants.FieldName; -import com.appsmith.server.constants.MigrationStatus; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; -import com.appsmith.server.exceptions.AppsmithError; -import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.helpers.CollectionUtils; -import com.appsmith.server.helpers.FeatureFlagMigrationHelper; -import com.appsmith.server.repositories.CacheableRepositoryHelper; -import com.appsmith.server.repositories.TenantRepository; -import com.appsmith.server.services.AnalyticsService; -import com.appsmith.server.services.BaseService; -import com.appsmith.server.services.ConfigService; -import com.appsmith.server.solutions.EnvManager; -import io.micrometer.observation.ObservationRegistry; -import jakarta.validation.Validator; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; -import org.springframework.util.StringUtils; -import reactor.core.observability.micrometer.Micrometer; -import reactor.core.publisher.Mono; - -import java.util.Map; - -import static com.appsmith.external.constants.spans.TenantSpan.FETCH_DEFAULT_TENANT_SPAN; -import static com.appsmith.external.constants.spans.TenantSpan.FETCH_TENANT_CACHE_POST_DESERIALIZATION_ERROR_SPAN; -import static com.appsmith.server.acl.AclPermission.MANAGE_TENANT; -import static java.lang.Boolean.TRUE; - -@Slf4j -public class TenantServiceCEImpl extends BaseService implements TenantServiceCE { - - private String tenantId = null; - - private final ConfigService configService; - - private final EnvManager envManager; - - private final FeatureFlagMigrationHelper featureFlagMigrationHelper; - - private final CacheableRepositoryHelper cacheableRepositoryHelper; - - private final CommonConfig commonConfig; - private final ObservationRegistry observationRegistry; - - public TenantServiceCEImpl( - Validator validator, - TenantRepository repository, - AnalyticsService analyticsService, - ConfigService configService, - @Lazy EnvManager envManager, - FeatureFlagMigrationHelper featureFlagMigrationHelper, - CacheableRepositoryHelper cacheableRepositoryHelper, - CommonConfig commonConfig, - ObservationRegistry observationRegistry) { - super(validator, repository, analyticsService); - this.configService = configService; - this.envManager = envManager; - this.featureFlagMigrationHelper = featureFlagMigrationHelper; - this.cacheableRepositoryHelper = cacheableRepositoryHelper; - this.commonConfig = commonConfig; - this.observationRegistry = observationRegistry; - } - - @Override - public Mono getDefaultTenantId() { - - // If the value exists in cache, return it as is - if (StringUtils.hasLength(tenantId)) { - return Mono.just(tenantId); - } - return repository.findBySlug(FieldName.DEFAULT).map(Tenant::getId).map(tenantId -> { - // Set the cache value before returning. - this.tenantId = tenantId; - return tenantId; - }); - } - - @Override - public Mono updateTenantConfiguration(String tenantId, TenantConfiguration tenantConfiguration) { - Mono evictTenantCache = cacheableRepositoryHelper.evictCachedTenant(tenantId); - return repository - .findById(tenantId, MANAGE_TENANT) - .switchIfEmpty(Mono.error( - new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.TENANT, tenantId))) - .flatMap(tenant -> { - TenantConfiguration oldtenantConfiguration = tenant.getTenantConfiguration(); - if (oldtenantConfiguration == null) { - oldtenantConfiguration = new TenantConfiguration(); - } - Mono> envMono = Mono.empty(); - // instance admin is setting the email verification to true but the SMTP settings are not configured - if (tenantConfiguration.isEmailVerificationEnabled() == Boolean.TRUE) { - envMono = envManager.getAllNonEmpty().flatMap(properties -> { - String mailHost = properties.get("APPSMITH_MAIL_HOST"); - if (mailHost == null || mailHost == "") { - return Mono.error(new AppsmithException(AppsmithError.INVALID_SMTP_CONFIGURATION)); - } - return Mono.empty(); - }); - } - - return envMono.then(Mono.zip(Mono.just(oldtenantConfiguration), Mono.just(tenant))); - }) - .flatMap(tuple2 -> { - Tenant tenant = tuple2.getT2(); - TenantConfiguration oldConfig = tuple2.getT1(); - AppsmithBeanUtils.copyNestedNonNullProperties(tenantConfiguration, oldConfig); - tenant.setTenantConfiguration(oldConfig); - Mono updatedTenantMono = repository - .updateById(tenantId, tenant, MANAGE_TENANT) - .cache(); - // Firstly updating the Tenant object in the database and then evicting the cache. - // returning the updatedTenant, notice the updatedTenantMono is cached using .cache() - // hence it will not be evaluated again - return updatedTenantMono - .then(Mono.defer(() -> evictTenantCache)) - .then(updatedTenantMono); - }); - } - - @Override - public Mono findById(String tenantId, AclPermission permission) { - return repository - .findById(tenantId, permission) - .switchIfEmpty( - Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, "tenantId", tenantId))); - } - - @Override - public Mono getTenantConfiguration(Mono dbTenantMono) { - String adminEmailDomainHash = commonConfig.getAdminEmailDomainHash(); - Mono clientTenantMono = configService.getInstanceId().map(instanceId -> { - final Tenant tenant = new Tenant(); - tenant.setInstanceId(instanceId); - tenant.setAdminEmailDomainHash(adminEmailDomainHash); - - final TenantConfiguration config = new TenantConfiguration(); - tenant.setTenantConfiguration(config); - - config.setGoogleMapsKey(System.getenv("APPSMITH_GOOGLE_MAPS_API_KEY")); - - if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GOOGLE_CLIENT_ID"))) { - config.addThirdPartyAuth("google"); - } - - if (StringUtils.hasText(System.getenv("APPSMITH_OAUTH2_GITHUB_CLIENT_ID"))) { - config.addThirdPartyAuth("github"); - } - - config.setIsFormLoginEnabled(!"true".equals(System.getenv("APPSMITH_FORM_LOGIN_DISABLED"))); - - return tenant; - }); - - return Mono.zip(dbTenantMono, clientTenantMono).flatMap(tuple -> { - Tenant dbTenant = tuple.getT1(); - Tenant clientTenant = tuple.getT2(); - return getClientPertinentTenant(dbTenant, clientTenant); - }); - } - - /* - * For now, returning just the instance-id, with an empty tenantConfiguration object in this class. Will enhance - * this function once we start saving other pertinent environment variables in the tenant collection. - */ - @Override - public Mono getTenantConfiguration() { - Mono dbTenantMono = getDefaultTenant(); - return getTenantConfiguration(dbTenantMono); - } - - @Override - public Mono getDefaultTenant() { - // Fetching Tenant from redis cache - return getDefaultTenantId() - .flatMap(tenantId -> cacheableRepositoryHelper.fetchDefaultTenant(tenantId)) - .name(FETCH_DEFAULT_TENANT_SPAN) - .tap(Micrometer.observation(observationRegistry)) - .flatMap(tenant -> repository.setUserPermissionsInObject(tenant).switchIfEmpty(Mono.just(tenant))) - .onErrorResume(e -> { - e.printStackTrace(); - log.error("Error fetching default tenant from redis : {}", e.getMessage()); - // If there is an error fetching the tenant from the cache, then evict the cache and fetching from - // the db. This handles the case for deserialization errors. This prevents the entire instance to - // go down if tenant cache is corrupted. - // More info - https://github.com/appsmithorg/appsmith/issues/33504 - log.info("Evicting the default tenant from cache and fetching from the database!"); - return cacheableRepositoryHelper - .evictCachedTenant(tenantId) - .then(cacheableRepositoryHelper - .fetchDefaultTenant(tenantId) - .map(tenant -> { - if (tenant.getTenantConfiguration() == null) { - tenant.setTenantConfiguration(new TenantConfiguration()); - } - return tenant; - })) - .name(FETCH_TENANT_CACHE_POST_DESERIALIZATION_ERROR_SPAN) - .tap(Micrometer.observation(observationRegistry)) - .flatMap(tenant -> repository - .setUserPermissionsInObject(tenant) - .switchIfEmpty(Mono.just(tenant))); - }); - } - - @Override - public Mono updateDefaultTenantConfiguration(TenantConfiguration tenantConfiguration) { - return getDefaultTenantId() - .flatMap(tenantId -> updateTenantConfiguration(tenantId, tenantConfiguration)) - .flatMap(updatedTenant -> getTenantConfiguration()); - } - - /** - * To get the Tenant with values that are pertinent to the client - * @param dbTenant Original tenant from the database - * @param clientTenant Tenant object that is sent to the client, can be null - * @return Mono - */ - protected Mono getClientPertinentTenant(Tenant dbTenant, Tenant clientTenant) { - if (clientTenant == null) { - clientTenant = new Tenant(); - clientTenant.setTenantConfiguration(new TenantConfiguration()); - } - - final TenantConfiguration tenantConfiguration = clientTenant.getTenantConfiguration(); - - // Only copy the values that are pertinent to the client - tenantConfiguration.copyNonSensitiveValues(dbTenant.getTenantConfiguration()); - clientTenant.setUserPermissions(dbTenant.getUserPermissions()); - - return Mono.just(clientTenant); - } - - // This function is used to save the tenant object in the database and evict the cache - @Override - public Mono save(Tenant tenant) { - Mono evictTenantCache = cacheableRepositoryHelper.evictCachedTenant(tenantId); - Mono savedTenantMono = repository.save(tenant).cache(); - return savedTenantMono.then(Mono.defer(() -> evictTenantCache)).then(savedTenantMono); - } - - /** - * This function checks if there are any pending migrations for feature flags and execute them. - * @param tenant tenant for which the migrations need to be executed - * @return tenant with migrations executed - */ - @Override - public Mono checkAndExecuteMigrationsForTenantFeatureFlags(Tenant tenant) { - if (!isMigrationRequired(tenant)) { - return Mono.just(tenant); - } - Map featureMigrationTypeMap = - tenant.getTenantConfiguration().getFeaturesWithPendingMigration(); - - FeatureFlagEnum featureFlagEnum = - featureMigrationTypeMap.keySet().stream().findFirst().orElse(null); - return featureFlagMigrationHelper - .checkAndExecuteMigrationsForFeatureFlag(tenant, featureFlagEnum) - .flatMap(isSuccessful -> { - if (TRUE.equals(isSuccessful)) { - featureMigrationTypeMap.remove(featureFlagEnum); - if (CollectionUtils.isNullOrEmpty(featureMigrationTypeMap)) { - tenant.getTenantConfiguration().setMigrationStatus(MigrationStatus.COMPLETED); - } else { - tenant.getTenantConfiguration().setMigrationStatus(MigrationStatus.IN_PROGRESS); - } - return this.save(tenant) - // Fetch the tenant again from DB to make sure the downstream chain is consuming the - // latest - // DB object and not the modified one because of the client pertinent changes - .then(repository.findById(tenant.getId())) - .flatMap(this::checkAndExecuteMigrationsForTenantFeatureFlags); - } - return Mono.error( - new AppsmithException(AppsmithError.FeatureFlagMigrationFailure, featureFlagEnum, "")); - }); - } - - @Override - public Mono retrieveById(String id) { - if (!StringUtils.hasLength(id)) { - return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID)); - } - return repository.findById(id); - } - - /** - * This function updates the tenant object in the database and evicts the cache - * @param tenantId - * @param tenant - * @return - */ - @Override - public Mono update(String tenantId, Tenant tenant) { - Mono evictTenantCache = cacheableRepositoryHelper.evictCachedTenant(tenantId); - Mono updatedTenantMono = super.update(tenantId, tenant).cache(); - return updatedTenantMono.then(Mono.defer(() -> evictTenantCache)).then(updatedTenantMono); - } - - /** - * This function checks if the tenant needs to be restarted and restarts after the feature flag migrations are - * executed. - * - * @return - */ - @Override - public Mono restartTenant() { - // Avoid dependency on user context as this method will be called internally by the server - Mono defaultTenantMono = this.getDefaultTenantId().flatMap(this::retrieveById); - return defaultTenantMono.flatMap(updatedTenant -> { - if (TRUE.equals(updatedTenant.getTenantConfiguration().getIsRestartRequired())) { - log.debug("Triggering tenant restart after the feature flag migrations are executed"); - TenantConfiguration tenantConfiguration = updatedTenant.getTenantConfiguration(); - tenantConfiguration.setIsRestartRequired(false); - return this.update(updatedTenant.getId(), updatedTenant).then(envManager.restartWithoutAclCheck()); - } - return Mono.empty(); - }); - } - - private boolean isMigrationRequired(Tenant tenant) { - return tenant.getTenantConfiguration() != null - && (!CollectionUtils.isNullOrEmpty( - tenant.getTenantConfiguration().getFeaturesWithPendingMigration()) - || (CollectionUtils.isNullOrEmpty( - tenant.getTenantConfiguration().getFeaturesWithPendingMigration()) - && !MigrationStatus.COMPLETED.equals( - tenant.getTenantConfiguration().getMigrationStatus()))); - } -} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UsagePulseServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UsagePulseServiceCEImpl.java index 55027b06933b..4a041fa0c323 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UsagePulseServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UsagePulseServiceCEImpl.java @@ -11,8 +11,8 @@ import com.appsmith.server.helpers.ce.bridge.BridgeUpdate; import com.appsmith.server.repositories.UsagePulseRepository; import com.appsmith.server.services.ConfigService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserService; import lombok.RequiredArgsConstructor; import org.apache.commons.codec.digest.DigestUtils; @@ -33,7 +33,7 @@ public class UsagePulseServiceCEImpl implements UsagePulseServiceCE { private final UserService userService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final ConfigService configService; @@ -64,43 +64,43 @@ public Mono createPulse(UsagePulseDTO usagePulseDTO) { usagePulse.setViewMode(usagePulseDTO.getViewMode()); Mono currentUserMono = sessionUserService.getCurrentUser(); - // TODO: Change to getCurrentTenantId once multi-tenancy in introduced - Mono tenantIdMono = tenantService.getDefaultTenantId(); + Mono defaultOrganizationIdMono = organizationService.getDefaultOrganizationId(); Mono instanceIdMono = configService.getInstanceId(); - return Mono.zip(currentUserMono, tenantIdMono, instanceIdMono).flatMap(tuple -> { - User user = tuple.getT1(); - String tenantId = tuple.getT2(); - String instanceId = tuple.getT3(); - usagePulse.setTenantId(tenantId); - usagePulse.setInstanceId(instanceId); - - if (user.isAnonymous()) { - if (null == usagePulseDTO.getAnonymousUserId()) { - return Mono.error( - new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ANONYMOUS_USER_ID)); - } - usagePulse.setIsAnonymousUser(true); - usagePulse.setUser(usagePulseDTO.getAnonymousUserId()); - return save(usagePulse); - } - usagePulse.setIsAnonymousUser(false); - BridgeUpdate updateUserObj = Bridge.update(); - - String hashedEmail = user.getHashedEmail(); - if (StringUtils.isEmpty(hashedEmail)) { - hashedEmail = DigestUtils.sha256Hex(user.getEmail()); - // Hashed user email is stored to user for future mapping of user and pulses - updateUserObj.set(User.Fields.hashedEmail, hashedEmail); - } - usagePulse.setUser(hashedEmail); - - updateUserObj.set(User.Fields.lastActiveAt, Instant.now()); - - return userService - .updateWithoutPermission(user.getId(), updateUserObj) - .then(save(usagePulse)); - }); + return Mono.zip(currentUserMono, defaultOrganizationIdMono, instanceIdMono) + .flatMap(tuple -> { + User user = tuple.getT1(); + String organizationId = tuple.getT2(); + String instanceId = tuple.getT3(); + usagePulse.setOrganizationId(organizationId); + usagePulse.setInstanceId(instanceId); + + if (user.isAnonymous()) { + if (null == usagePulseDTO.getAnonymousUserId()) { + return Mono.error(new AppsmithException( + AppsmithError.INVALID_PARAMETER, FieldName.ANONYMOUS_USER_ID)); + } + usagePulse.setIsAnonymousUser(true); + usagePulse.setUser(usagePulseDTO.getAnonymousUserId()); + return save(usagePulse); + } + usagePulse.setIsAnonymousUser(false); + BridgeUpdate updateUserObj = Bridge.update(); + + String hashedEmail = user.getHashedEmail(); + if (StringUtils.isEmpty(hashedEmail)) { + hashedEmail = DigestUtils.sha256Hex(user.getEmail()); + // Hashed user email is stored to user for future mapping of user and pulses + updateUserObj.set(User.Fields.hashedEmail, hashedEmail); + } + usagePulse.setUser(hashedEmail); + + updateUserObj.set(User.Fields.lastActiveAt, Instant.now()); + + return userService + .updateWithoutPermission(user.getId(), updateUserObj) + .then(save(usagePulse)); + }); } /** diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java index 0f2180207caf..eac40e84e845 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserDataServiceCEImpl.java @@ -20,8 +20,8 @@ import com.appsmith.server.services.AssetService; import com.appsmith.server.services.BaseService; import com.appsmith.server.services.FeatureFlagService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.solutions.ReleaseNotesService; import jakarta.validation.Validator; import org.apache.commons.lang3.ObjectUtils; @@ -54,7 +54,7 @@ public class UserDataServiceCEImpl extends BaseService getForCurrentUser() { @Override public Mono getForUserEmail(String email) { - return tenantService - .getDefaultTenantId() - .flatMap(tenantId -> userRepository.findByEmailAndTenantId(email, tenantId)) + return organizationService + .getDefaultOrganizationId() + .flatMap(organizationId -> userRepository.findByEmailAndOrganizationId(email, organizationId)) .flatMap(this::getForUser); } @@ -124,9 +124,10 @@ public Mono> getProfilePhotoAssetIdsForUserIds(Collection updateForCurrentUser(UserData updates) { return sessionUserService .getCurrentUser() - .flatMap(user -> tenantService - .getDefaultTenantId() - .flatMap(tenantId -> userRepository.findByEmailAndTenantId(user.getEmail(), tenantId))) + .flatMap(user -> organizationService + .getDefaultOrganizationId() + .flatMap(organizationId -> + userRepository.findByEmailAndOrganizationId(user.getEmail(), organizationId))) .flatMap(user -> updateForUser(user, updates)); } @@ -170,9 +171,10 @@ public Mono setViewedCurrentVersionReleaseNotes(User user, String version) } return Mono.justOrEmpty(user.getId()) - .switchIfEmpty(tenantService - .getDefaultTenantId() - .flatMap(tenantId -> userRepository.findByEmailAndTenantId(user.getEmail(), tenantId)) + .switchIfEmpty(organizationService + .getDefaultOrganizationId() + .flatMap(organizationId -> + userRepository.findByEmailAndOrganizationId(user.getEmail(), organizationId)) .flatMap(user1 -> Mono.justOrEmpty(user1.getId()))) .flatMap(userId -> repository .saveReleaseNotesViewedVersion(userId, version) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCE.java index 24dfffcbc0a9..108138c5078a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCE.java @@ -19,7 +19,7 @@ public interface UserServiceCE extends CrudService { Mono findByEmail(String email); - Mono findByEmailAndTenantId(String email, String tenantId); + Mono findByEmailAndOrganizationId(String email, String organizationId); Mono forgotPasswordTokenGenerate(ResetUserPasswordDTO resetUserPasswordDTO); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java index 4f5d7a690c3f..c6ced67e84f9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java @@ -7,9 +7,9 @@ import com.appsmith.server.constants.RateLimitConstants; import com.appsmith.server.domains.EmailVerificationToken; import com.appsmith.server.domains.LoginSource; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.PasswordResetToken; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; import com.appsmith.server.domains.Workspace; @@ -31,9 +31,9 @@ import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.BaseService; import com.appsmith.server.services.EmailService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.PACConfigurationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.WorkspaceService; import jakarta.validation.Validator; @@ -77,7 +77,7 @@ import static com.appsmith.server.acl.AclPermission.MANAGE_USERS; import static com.appsmith.server.constants.FieldName.DEFAULT; -import static com.appsmith.server.constants.FieldName.TENANT; +import static com.appsmith.server.constants.FieldName.ORGANIZATION; import static com.appsmith.server.helpers.RedirectHelper.DEFAULT_REDIRECT_URL; import static com.appsmith.server.helpers.ValidationUtils.LOGIN_PASSWORD_MAX_LENGTH; import static com.appsmith.server.helpers.ValidationUtils.LOGIN_PASSWORD_MIN_LENGTH; @@ -97,7 +97,7 @@ public class UserServiceCEImpl extends BaseService private final CommonConfig commonConfig; private final UserDataService userDataService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final UserUtils userUtils; private final EmailService emailService; private final RateLimitService rateLimitService; @@ -128,7 +128,7 @@ public UserServiceCEImpl( PasswordEncoder passwordEncoder, CommonConfig commonConfig, UserDataService userDataService, - TenantService tenantService, + OrganizationService organizationService, UserUtils userUtils, EmailVerificationTokenRepository emailVerificationTokenRepository, EmailService emailService, @@ -143,7 +143,7 @@ public UserServiceCEImpl( this.passwordEncoder = passwordEncoder; this.commonConfig = commonConfig; this.userDataService = userDataService; - this.tenantService = tenantService; + this.organizationService = organizationService; this.userUtils = userUtils; this.rateLimitService = rateLimitService; this.emailVerificationTokenRepository = emailVerificationTokenRepository; @@ -154,12 +154,14 @@ public UserServiceCEImpl( @Override public Mono findByEmail(String email) { - return tenantService.getDefaultTenantId().flatMap(tenantId -> findByEmailAndTenantId(email, tenantId)); + return organizationService + .getDefaultOrganizationId() + .flatMap(organizationId -> findByEmailAndOrganizationId(email, organizationId)); } @Override - public Mono findByEmailAndTenantId(String email, String tenantId) { - return repository.findByEmailAndTenantId(email, tenantId); + public Mono findByEmailAndOrganizationId(String email, String organizationId) { + return repository.findByEmailAndOrganizationId(email, organizationId); } /** @@ -305,9 +307,10 @@ public Mono resetPasswordAfterForgotPassword(String encryptedToken, Use return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.TOKEN)); } - Mono tenantMono = tenantService - .getDefaultTenant() - .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, DEFAULT, TENANT))); + Mono organizationMono = organizationService + .getDefaultOrganization() + .switchIfEmpty( + Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, DEFAULT, ORGANIZATION))); return passwordResetTokenRepository .findByEmail(emailTokenDTO.getEmail()) @@ -325,13 +328,14 @@ public Mono resetPasswordAfterForgotPassword(String encryptedToken, Use .findByEmail(emailAddress) .switchIfEmpty(Mono.error( new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.USER, emailAddress))) - .zipWith(tenantMono) + .zipWith(organizationMono) .flatMap(tuple -> { User userFromDb = tuple.getT1(); - TenantConfiguration tenantConfiguration = - tuple.getT2().getTenantConfiguration(); - boolean isStrongPasswordPolicyEnabled = tenantConfiguration != null - && Boolean.TRUE.equals(tenantConfiguration.getIsStrongPasswordPolicyEnabled()); + OrganizationConfiguration organizationConfiguration = + tuple.getT2().getOrganizationConfiguration(); + boolean isStrongPasswordPolicyEnabled = organizationConfiguration != null + && Boolean.TRUE.equals( + organizationConfiguration.getIsStrongPasswordPolicyEnabled()); if (!validateUserPassword(user.getPassword(), isStrongPasswordPolicyEnabled)) { return isStrongPasswordPolicyEnabled @@ -395,19 +399,19 @@ public Mono userCreate(User user, boolean isAdminUser) { // convert the user email to lowercase user.setEmail(user.getEmail().toLowerCase()); - Mono userWithTenantMono = Mono.just(user).flatMap(userBeforeSave -> { - if (userBeforeSave.getTenantId() == null) { - return tenantService.getDefaultTenantId().map(tenantId -> { - userBeforeSave.setTenantId(tenantId); + Mono userWithOrgMono = Mono.just(user).flatMap(userBeforeSave -> { + if (userBeforeSave.getOrganizationId() == null) { + return organizationService.getDefaultOrganizationId().map(organizationId -> { + userBeforeSave.setOrganizationId(organizationId); return userBeforeSave; }); } - // The tenant has been set already. No need to set the default tenant id. + // The org has been set already. No need to set the default org id. return Mono.just(userBeforeSave); }); // Save the new user - return userWithTenantMono + return userWithOrgMono .flatMap(this::validateObject) .flatMap(repository::save) .flatMap(this::addUserPoliciesAndSaveToRepo) @@ -674,7 +678,8 @@ public Mono buildUserProfileDTO(User user) { Mono userFromDbMono = findByEmail(user.getEmail()).cache(); - Mono isSuperUserMono = userFromDbMono.flatMap(userUtils::isSuperUser); + Mono isSuperUserMono = + userFromDbMono.flatMap(userUtils::isSuperUser).defaultIfEmpty(false); return Mono.zip( isUsersEmpty(), @@ -754,13 +759,13 @@ public Mono resendEmailVerification( if (TRUE.equals(user.getEmailVerified())) { return Mono.error(new AppsmithException(AppsmithError.USER_ALREADY_VERIFIED)); } - return tenantService.getTenantConfiguration().flatMap(tenant -> { + return organizationService.getOrganizationConfiguration().flatMap(organization -> { Boolean emailVerificationEnabled = - tenant.getTenantConfiguration().isEmailVerificationEnabled(); - // Email verification not enabled at tenant + organization.getOrganizationConfiguration().isEmailVerificationEnabled(); + // Email verification not enabled at organization level if (!TRUE.equals(emailVerificationEnabled)) { return Mono.error( - new AppsmithException(AppsmithError.TENANT_EMAIL_VERIFICATION_NOT_ENABLED)); + new AppsmithException(AppsmithError.ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED)); } return emailVerificationTokenRepository .findByEmail(user.getEmail()) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java index 3430bb83b993..239aae4c7da8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java @@ -13,9 +13,9 @@ import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.AppsmithComparators; import com.appsmith.server.repositories.UserRepository; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.PermissionGroupService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.WorkspaceService; import com.appsmith.server.solutions.PermissionGroupPermission; @@ -50,7 +50,7 @@ public class UserWorkspaceServiceCEImpl implements UserWorkspaceServiceCE { private final UserRepository userRepository; private final UserDataService userDataService; private final PermissionGroupService permissionGroupService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final WorkspacePermission workspacePermission; private final PermissionGroupPermission permissionGroupPermission; @@ -61,7 +61,7 @@ public UserWorkspaceServiceCEImpl( UserRepository userRepository, UserDataService userDataService, PermissionGroupService permissionGroupService, - TenantService tenantService, + OrganizationService organizationService, WorkspacePermission workspacePermission, PermissionGroupPermission permissionGroupPermission) { this.sessionUserService = sessionUserService; @@ -69,7 +69,7 @@ public UserWorkspaceServiceCEImpl( this.userRepository = userRepository; this.userDataService = userDataService; this.permissionGroupService = permissionGroupService; - this.tenantService = tenantService; + this.organizationService = organizationService; this.workspacePermission = workspacePermission; this.permissionGroupPermission = permissionGroupPermission; } @@ -147,9 +147,10 @@ public Mono updatePermissionGroupForMember( .cache(); // Get the user - Mono userMono = tenantService - .getDefaultTenantId() - .flatMap(tenantId -> userRepository.findByEmailAndTenantId(changeUserGroupDTO.getUsername(), tenantId)) + Mono userMono = organizationService + .getDefaultOrganizationId() + .flatMap(organizationId -> + userRepository.findByEmailAndOrganizationId(changeUserGroupDTO.getUsername(), organizationId)) .switchIfEmpty(Mono.error(new AppsmithException( AppsmithError.NO_RESOURCE_FOUND, FieldName.USER, changeUserGroupDTO.getUsername()))) .cache(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java index 40ce39ce0298..071001f4d981 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java @@ -28,7 +28,7 @@ public interface WorkspaceServiceCE extends CrudService { Mono findByIdAndPluginsPluginId(String workspaceId, String pluginId); - Flux findByIdsIn(Set ids, String tenantId, AclPermission permission); + Flux findByIdsIn(Set ids, String organizationId, AclPermission permission); Flux getAll(AclPermission permission); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java index 7758ee3f0c58..cdcd6187a86f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java @@ -193,7 +193,7 @@ protected void prepareWorkspaceToCreate(Workspace workspace, User user) { } workspace.setSlug(TextUtils.makeSlug(workspace.getName())); - workspace.setTenantId(user.getTenantId()); + workspace.setOrganizationId(user.getOrganizationId()); } protected Mono createWorkspaceDependents(Workspace createdWorkspace) { @@ -240,7 +240,7 @@ private Mono> generateDefaultPermissionGroupsWithoutPermiss adminPermissionGroup.setName(generateDefaultRoleNameForResource(ADMINISTRATOR, workspaceName)); adminPermissionGroup.setDefaultDomainId(workspaceId); adminPermissionGroup.setDefaultDomainType(Workspace.class.getSimpleName()); - adminPermissionGroup.setTenantId(workspace.getTenantId()); + adminPermissionGroup.setOrganizationId(workspace.getOrganizationId()); adminPermissionGroup.setDescription(WORKSPACE_ADMINISTRATOR_DESCRIPTION); adminPermissionGroup.setPermissions(Set.of()); @@ -249,7 +249,7 @@ private Mono> generateDefaultPermissionGroupsWithoutPermiss developerPermissionGroup.setName(generateDefaultRoleNameForResource(DEVELOPER, workspaceName)); developerPermissionGroup.setDefaultDomainId(workspaceId); developerPermissionGroup.setDefaultDomainType(Workspace.class.getSimpleName()); - developerPermissionGroup.setTenantId(workspace.getTenantId()); + developerPermissionGroup.setOrganizationId(workspace.getOrganizationId()); developerPermissionGroup.setDescription(WORKSPACE_DEVELOPER_DESCRIPTION); developerPermissionGroup.setPermissions(Set.of()); @@ -258,7 +258,7 @@ private Mono> generateDefaultPermissionGroupsWithoutPermiss viewerPermissionGroup.setName(generateDefaultRoleNameForResource(VIEWER, workspaceName)); viewerPermissionGroup.setDefaultDomainId(workspaceId); viewerPermissionGroup.setDefaultDomainType(Workspace.class.getSimpleName()); - viewerPermissionGroup.setTenantId(workspace.getTenantId()); + viewerPermissionGroup.setOrganizationId(workspace.getOrganizationId()); viewerPermissionGroup.setDescription(WORKSPACE_VIEWER_DESCRIPTION); viewerPermissionGroup.setPermissions(Set.of()); @@ -456,10 +456,10 @@ public Mono findByIdAndPluginsPluginId(String workspaceId, String plu } @Override - public Flux findByIdsIn(Set ids, String tenantId, AclPermission permission) { + public Flux findByIdsIn(Set ids, String organizationId, AclPermission permission) { Sort sort = Sort.by(FieldName.NAME); - return repository.findByIdsIn(ids, tenantId, permission, sort); + return repository.findByIdsIn(ids, organizationId, permission, sort); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ConsolidatedAPIServiceCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ConsolidatedAPIServiceCECompatibleImpl.java index c6f94b2cf303..5baec349b02a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ConsolidatedAPIServiceCECompatibleImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ConsolidatedAPIServiceCECompatibleImpl.java @@ -11,9 +11,9 @@ import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.MockDataService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.ProductAlertService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import com.appsmith.server.services.ce.ConsolidatedAPIServiceCEImpl; @@ -26,7 +26,7 @@ public ConsolidatedAPIServiceCECompatibleImpl( SessionUserService sessionUserService, UserService userService, UserDataService userDataService, - TenantService tenantService, + OrganizationService organizationService, ProductAlertService productAlertService, NewPageService newPageService, NewActionService newActionService, @@ -45,7 +45,7 @@ public ConsolidatedAPIServiceCECompatibleImpl( sessionUserService, userService, userDataService, - tenantService, + organizationService, productAlertService, newPageService, newActionService, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java index be6024011cb8..3d9c82438b9f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java @@ -4,8 +4,8 @@ import com.appsmith.server.repositories.PermissionGroupRepository; import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.ce.PermissionGroupServiceCEImpl; import com.appsmith.server.solutions.PermissionGroupPermission; import com.appsmith.server.solutions.PolicySolution; @@ -20,7 +20,7 @@ public PermissionGroupServiceCECompatibleImpl( PermissionGroupRepository repository, AnalyticsService analyticsService, SessionUserService sessionUserService, - TenantService tenantService, + OrganizationService organizationService, UserRepository userRepository, PolicySolution policySolution, ConfigRepository configRepository, @@ -30,7 +30,7 @@ public PermissionGroupServiceCECompatibleImpl( repository, analyticsService, sessionUserService, - tenantService, + organizationService, userRepository, policySolution, configRepository, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java index 7589ceac4a88..a3d91e7c9a44 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java @@ -9,9 +9,9 @@ import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.EmailService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.PACConfigurationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.WorkspaceService; import com.appsmith.server.services.ce.UserServiceCEImpl; @@ -31,7 +31,7 @@ public UserServiceCECompatibleImpl( PasswordEncoder passwordEncoder, CommonConfig commonConfig, UserDataService userDataService, - TenantService tenantService, + OrganizationService organizationService, UserUtils userUtils, EmailVerificationTokenRepository emailVerificationTokenRepository, EmailService emailService, @@ -48,7 +48,7 @@ public UserServiceCECompatibleImpl( passwordEncoder, commonConfig, userDataService, - tenantService, + organizationService, userUtils, emailVerificationTokenRepository, emailService, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java index 6f3413f55d94..47ec8c2b321d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java @@ -14,8 +14,8 @@ import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceContextService; import com.appsmith.server.services.FeatureFlagService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.solutions.ce.ActionExecutionSolutionCEImpl; import com.fasterxml.jackson.databind.ObjectMapper; import io.micrometer.observation.ObservationRegistry; @@ -41,7 +41,7 @@ public ActionExecutionSolutionImpl( DatasourceStorageService datasourceStorageService, EnvironmentPermission environmentPermission, ConfigService configService, - TenantService tenantService, + OrganizationService organizationService, CommonConfig commonConfig, ActionExecutionSolutionHelper actionExecutionSolutionHelper, FeatureFlagService featureFlagService) { @@ -63,7 +63,7 @@ public ActionExecutionSolutionImpl( datasourceStorageService, environmentPermission, configService, - tenantService, + organizationService, commonConfig, actionExecutionSolutionHelper, featureFlagService); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/DatasourceTriggerSolutionImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/DatasourceTriggerSolutionImpl.java index a892502e7ffb..71c7c1e9f8bb 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/DatasourceTriggerSolutionImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/DatasourceTriggerSolutionImpl.java @@ -8,7 +8,7 @@ import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceContextService; import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.solutions.ce.DatasourceTriggerSolutionCEImpl; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -29,7 +29,7 @@ public DatasourceTriggerSolutionImpl( DatasourcePermission datasourcePermission, EnvironmentPermission environmentPermission, ConfigService configService, - TenantService tenantService, + OrganizationService organizationService, FeatureFlagService featureFlagService) { super( datasourceService, @@ -42,7 +42,7 @@ public DatasourceTriggerSolutionImpl( datasourcePermission, environmentPermission, configService, - tenantService, + organizationService, featureFlagService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/EnvManagerImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/EnvManagerImpl.java index 865c9bf2dd82..974b359c4e86 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/EnvManagerImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/EnvManagerImpl.java @@ -10,9 +10,9 @@ import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.EmailService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.PermissionGroupService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserService; import com.appsmith.server.solutions.ce.EnvManagerCEImpl; import com.fasterxml.jackson.databind.ObjectMapper; @@ -38,7 +38,7 @@ public EnvManagerImpl( PermissionGroupService permissionGroupService, ConfigService configService, UserUtils userUtils, - TenantService tenantService, + OrganizationService organizationService, ObjectMapper objectMapper, EmailService emailService) { @@ -56,7 +56,7 @@ public EnvManagerImpl( permissionGroupService, configService, userUtils, - tenantService, + organizationService, objectMapper, emailService); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ScheduledTaskImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ScheduledTaskImpl.java index 7b16eae7de6f..4ea28396a8b4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ScheduledTaskImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ScheduledTaskImpl.java @@ -1,11 +1,11 @@ package com.appsmith.server.solutions; import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.solutions.ce.ScheduledTaskCEImpl; public class ScheduledTaskImpl extends ScheduledTaskCEImpl implements ScheduledTask { - public ScheduledTaskImpl(FeatureFlagService featureFlagService, TenantService tenantService) { - super(featureFlagService, tenantService); + public ScheduledTaskImpl(FeatureFlagService featureFlagService, OrganizationService organizationService) { + super(featureFlagService, organizationService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/UserSignupImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/UserSignupImpl.java index 29b03db32ad7..2cca8735001b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/UserSignupImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/UserSignupImpl.java @@ -7,7 +7,7 @@ import com.appsmith.server.services.CaptchaService; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.EmailService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import com.appsmith.server.solutions.ce.UserSignupCEImpl; @@ -29,7 +29,7 @@ public UserSignupImpl( UserUtils userUtils, NetworkUtils networkUtils, EmailService emailService, - TenantService tenantService) { + OrganizationService organizationService) { super( userService, @@ -42,6 +42,6 @@ public UserSignupImpl( userUtils, networkUtils, emailService, - tenantService); + organizationService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java index 78737b83b78a..3c717e069713 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java @@ -46,8 +46,8 @@ import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceContextService; import com.appsmith.server.services.FeatureFlagService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.solutions.ActionPermission; import com.appsmith.server.solutions.DatasourcePermission; import com.appsmith.server.solutions.EnvironmentPermission; @@ -121,7 +121,7 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE private final DatasourceStorageService datasourceStorageService; private final EnvironmentPermission environmentPermission; private final ConfigService configService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final ActionExecutionSolutionHelper actionExecutionSolutionHelper; private final CommonConfig commonConfig; private final FeatureFlagService featureFlagService; @@ -151,7 +151,7 @@ public ActionExecutionSolutionCEImpl( DatasourceStorageService datasourceStorageService, EnvironmentPermission environmentPermission, ConfigService configService, - TenantService tenantService, + OrganizationService organizationService, CommonConfig commonConfig, ActionExecutionSolutionHelper actionExecutionSolutionHelper, FeatureFlagService featureFlagService) { @@ -172,7 +172,7 @@ public ActionExecutionSolutionCEImpl( this.datasourceStorageService = datasourceStorageService; this.environmentPermission = environmentPermission; this.configService = configService; - this.tenantService = tenantService; + this.organizationService = organizationService; this.commonConfig = commonConfig; this.actionExecutionSolutionHelper = actionExecutionSolutionHelper; this.featureFlagService = featureFlagService; @@ -252,16 +252,16 @@ private Mono getTrueEnvironmentId( */ private Mono populateExecuteActionDTO(ExecuteActionDTO executeActionDTO, NewAction newAction) { Mono instanceIdMono = configService.getInstanceId(); - Mono defaultTenantIdMono = tenantService.getDefaultTenantId(); + Mono defaultOrganizationIdMono = organizationService.getDefaultOrganizationId(); Mono systemInfoPopulatedExecuteActionDTOMono = actionExecutionSolutionHelper.populateExecuteActionDTOWithSystemInfo(executeActionDTO); return systemInfoPopulatedExecuteActionDTOMono.flatMap(populatedExecuteActionDTO -> Mono.zip( - instanceIdMono, defaultTenantIdMono) + instanceIdMono, defaultOrganizationIdMono) .map(tuple -> { String instanceId = tuple.getT1(); - String tenantId = tuple.getT2(); + String organizationId = tuple.getT2(); populatedExecuteActionDTO.setActionId(newAction.getId()); populatedExecuteActionDTO.setWorkspaceId(newAction.getWorkspaceId()); if (TRUE.equals(executeActionDTO.getViewMode())) { @@ -272,7 +272,7 @@ private Mono populateExecuteActionDTO(ExecuteActionDTO execute newAction.getUnpublishedAction().getDatasource().getId()); } populatedExecuteActionDTO.setInstanceId(instanceId); - populatedExecuteActionDTO.setTenantId(tenantId); + populatedExecuteActionDTO.setOrganizationId(organizationId); return populatedExecuteActionDTO; })); } @@ -731,8 +731,10 @@ protected Mono verifyDatasourceAndMakeRequest( // Now that we have the context (connection details), execute the action. Instant requestedAt = Instant.now(); - Map features = featureFlagService.getCachedTenantFeatureFlags() != null - ? featureFlagService.getCachedTenantFeatureFlags().getFeatures() + Map features = featureFlagService.getCachedOrganizationFeatureFlags() != null + ? featureFlagService + .getCachedOrganizationFeatureFlags() + .getFeatures() : Collections.emptyMap(); // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java index b73dc33a26de..b934b4d0841b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java @@ -18,7 +18,7 @@ import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceContextService; import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.solutions.DatasourcePermission; import com.appsmith.server.solutions.DatasourceStructureSolution; import com.appsmith.server.solutions.EnvironmentPermission; @@ -54,7 +54,7 @@ public class DatasourceTriggerSolutionCEImpl implements DatasourceTriggerSolutio private final DatasourcePermission datasourcePermission; private final EnvironmentPermission environmentPermission; private final ConfigService configService; - private final TenantService tenantService; + private final OrganizationService organizationService; private final FeatureFlagService featureFlagService; public Mono trigger( @@ -110,8 +110,10 @@ public Mono trigger( // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag // Once thoroughly tested, this flag can be removed - Map featureFlagMap = featureFlagService.getCachedTenantFeatureFlags() != null - ? featureFlagService.getCachedTenantFeatureFlags().getFeatures() + Map featureFlagMap = featureFlagService.getCachedOrganizationFeatureFlags() != null + ? featureFlagService + .getCachedOrganizationFeatureFlags() + .getFeatures() : Collections.emptyMap(); return datasourceContextService @@ -164,11 +166,11 @@ public Mono trigger( private Mono populateTriggerRequestDto( TriggerRequestDTO triggerRequestDTO, Datasource datasource) { - return tenantService - .getDefaultTenantId() + return organizationService + .getDefaultOrganizationId() .zipWith(configService.getInstanceId()) .map(tuple -> { - triggerRequestDTO.setTenantId(tuple.getT1()); + triggerRequestDTO.setOrganizationId(tuple.getT1()); triggerRequestDTO.setInstanceId(tuple.getT2()); triggerRequestDTO.setWorkspaceId(datasource.getWorkspaceId()); return triggerRequestDTO; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvManagerCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvManagerCEImpl.java index af74b26950ed..72528b88a9b8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvManagerCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvManagerCEImpl.java @@ -7,8 +7,8 @@ import com.appsmith.server.configurations.GoogleRecaptchaConfig; import com.appsmith.server.constants.EnvVariables; import com.appsmith.server.constants.FieldName; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.dtos.TestEmailConfigRequestDTO; import com.appsmith.server.exceptions.AppsmithError; @@ -24,9 +24,9 @@ import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.EmailService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.PermissionGroupService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserService; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; @@ -108,7 +108,7 @@ public class EnvManagerCEImpl implements EnvManagerCE { private final UserUtils userUtils; - private final TenantService tenantService; + private final OrganizationService organizationService; private final ObjectMapper objectMapper; @@ -138,7 +138,7 @@ public EnvManagerCEImpl( PermissionGroupService permissionGroupService, ConfigService configService, UserUtils userUtils, - TenantService tenantService, + OrganizationService organizationService, ObjectMapper objectMapper, EmailService emailService) { @@ -155,7 +155,7 @@ public EnvManagerCEImpl( this.permissionGroupService = permissionGroupService; this.configService = configService; this.userUtils = userUtils; - this.tenantService = tenantService; + this.organizationService = organizationService; this.objectMapper = objectMapper; this.emailService = emailService; } @@ -172,12 +172,13 @@ public EnvManagerCEImpl( @Override public List transformEnvContent(String envContent, Map changes) { final Set variablesNotInWhitelist = new HashSet<>(changes.keySet()); - final Set tenantConfigWhitelist = allowedTenantConfiguration(); + final Set organizationConfigWhitelist = allowedOrganizationConfiguration(); - // We remove all the variables that aren't defined in our env variable whitelist or in the TenantConfiguration - // class. This is because the configuration can be saved either in the .env file or the tenant collection + // We remove all the variables that aren't defined in our env variable whitelist or in the + // OrganizationConfiguration + // class. This is because the configuration can be saved either in the .env file or the organization collection variablesNotInWhitelist.removeAll(VARIABLE_WHITELIST); - variablesNotInWhitelist.removeAll(tenantConfigWhitelist); + variablesNotInWhitelist.removeAll(organizationConfigWhitelist); if (!variablesNotInWhitelist.isEmpty()) { throw new AppsmithException(AppsmithError.GENERIC_BAD_REQUEST); @@ -263,7 +264,7 @@ private String unescapeFromShell(String input) { return valueBuilder.toString(); } - // Expect user object to be null when this method is getting called to run the tenant specific migrations without + // Expect user object to be null when this method is getting called to run the org specific migrations without // user context private Mono validateChanges(User user, Map changes) { if (changes.containsKey(APPSMITH_ADMIN_EMAILS.name())) { @@ -284,12 +285,12 @@ private Mono validateChanges(User user, Map changes) { } /** - * This function returns a set of String based on the JsonProperty annotations in the TenantConfiguration class + * This function returns a set of String based on the JsonProperty annotations in the OrganizationConfiguration class * * @return */ - private Set allowedTenantConfiguration() { - return AppsmithBeanUtils.getAllFields(TenantConfiguration.class) + private Set allowedOrganizationConfiguration() { + return AppsmithBeanUtils.getAllFields(OrganizationConfiguration.class) .map(field -> { JsonProperty jsonProperty = field.getDeclaredAnnotation(JsonProperty.class); return jsonProperty == null ? field.getName() : jsonProperty.value(); @@ -298,57 +299,61 @@ private Set allowedTenantConfiguration() { } /** - * This function sets the value in the TenantConfiguration object based on the JsonProperty annotation of the field + * This function sets the value in the OrganizationConfiguration object based on the JsonProperty annotation of the field * The key must be exactly equal to the json annotation * - * @param tenantConfiguration + * @param organizationConfiguration * @param key * @param value */ - private void setConfigurationByKey(TenantConfiguration tenantConfiguration, String key, String value) { - Stream fieldStream = AppsmithBeanUtils.getAllFields(TenantConfiguration.class); + private void setConfigurationByKey(OrganizationConfiguration organizationConfiguration, String key, String value) { + Stream fieldStream = AppsmithBeanUtils.getAllFields(OrganizationConfiguration.class); fieldStream.forEach(field -> { JsonProperty jsonProperty = field.getDeclaredAnnotation(JsonProperty.class); if (jsonProperty != null && jsonProperty.value().equals(key)) { try { field.setAccessible(true); Object typedValue = ConvertUtils.convert(value, field.getType()); - field.set(tenantConfiguration, typedValue); + field.set(organizationConfiguration, typedValue); } catch (IllegalAccessException e) { // Catch the error, log it and then do nothing. log.error( - "Got error while parsing the JSON annotations from TenantConfiguration class. Cause: ", e); + "Got error while parsing the JSON annotations from OrganizationConfiguration class. Cause: ", + e); } } else if (field.getName().equals(key)) { try { field.setAccessible(true); Object typedValue = ConvertUtils.convert(value, field.getType()); - field.set(tenantConfiguration, typedValue); + field.set(organizationConfiguration, typedValue); } catch (IllegalAccessException e) { // Catch the error, log it and then do nothing. - log.error("Got error while attempting to save property to TenantConfiguration class. Cause: ", e); + log.error( + "Got error while attempting to save property to OrganizationConfiguration class. Cause: ", + e); } } }); } - private Mono updateTenantConfiguration(String tenantId, Map changes) { - TenantConfiguration tenantConfiguration = new TenantConfiguration(); - // Write the changes to the tenant collection in configuration field + private Mono updateOrganizationConfiguration(String organizationId, Map changes) { + OrganizationConfiguration organizationConfiguration = new OrganizationConfiguration(); + // Write the changes to the organization collection in configuration field return Flux.fromIterable(changes.entrySet()) .map(map -> { String key = map.getKey(); String value = map.getValue(); - setConfigurationByKey(tenantConfiguration, key, value); + setConfigurationByKey(organizationConfiguration, key, value); return map; }) - .then(Mono.just(tenantConfiguration)) - .flatMap(updatedTenantConfig -> tenantService.updateTenantConfiguration(tenantId, tenantConfiguration)); + .then(Mono.just(organizationConfiguration)) + .flatMap(updatedOrganizationConfig -> + organizationService.updateOrganizationConfiguration(organizationId, organizationConfiguration)); } @Override public Mono applyChanges(Map changes, String originHeader) { - // This flow is pertinent for any variables that need to change in the .env file or be saved in the tenant + // This flow is pertinent for any variables that need to change in the .env file or be saved in the organization // configuration return verifyCurrentUserIsSuper() .flatMap(user -> validateChanges(user, changes).thenReturn(user)) @@ -356,8 +361,8 @@ public Mono applyChanges(Map changes, String originHeader) // For configuration variables, save the variables to the config collection instead of .env file // We ideally want to migrate all variables from .env file to the config collection for better // scalability - // Write the changes to the tenant collection in configuration field - .flatMap(originalVariables -> updateTenantConfiguration(user.getTenantId(), changes) + // Write the changes to the organization collection in configuration field + .flatMap(originalVariables -> updateOrganizationConfiguration(user.getOrganizationId(), changes) .then(sendAnalyticsEvent(user, originalVariables, changes)) .thenReturn(originalVariables))) .flatMap(originalValues -> { @@ -453,9 +458,9 @@ public Mono> applyChangesToEnvFileWithoutAclCheck(Map originalVariables = parseToMap(originalContent); final Map envFileChanges = new HashMap<>(changes); - final Set tenantConfigurationKeys = allowedTenantConfiguration(); + final Set organizationConfigurationKeys = allowedOrganizationConfiguration(); for (final String key : changes.keySet()) { - if (tenantConfigurationKeys.contains(key)) { + if (organizationConfigurationKeys.contains(key)) { envFileChanges.remove(key); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ScheduledTaskCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ScheduledTaskCEImpl.java index 9d385f2655fb..d34cd294fb4e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ScheduledTaskCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ScheduledTaskCEImpl.java @@ -2,7 +2,7 @@ import com.appsmith.server.helpers.LoadShifter; import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import io.micrometer.observation.annotation.Observed; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -16,19 +16,19 @@ public class ScheduledTaskCEImpl implements ScheduledTaskCE { private final FeatureFlagService featureFlagService; - private final TenantService tenantService; + private final OrganizationService organizationService; @Scheduled(initialDelay = 10 * 1000 /* ten seconds */, fixedRate = 30 * 60 * 1000 /* thirty minutes */) @Observed(name = "fetchFeatures") public void fetchFeatures() { - log.info("Fetching features for default tenant"); + log.info("Fetching features for default organization"); featureFlagService - .getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations() - .then(tenantService - .getDefaultTenant() - .flatMap(featureFlagService::checkAndExecuteMigrationsForTenantFeatureFlags) - .then(tenantService.restartTenant())) - .doOnError(error -> log.error("Error while fetching tenant feature flags", error)) + .getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations() + .then(organizationService + .getDefaultOrganization() + .flatMap(featureFlagService::checkAndExecuteMigrationsForOrganizationFeatureFlags) + .then(organizationService.restartOrganization())) + .doOnError(error -> log.error("Error while fetching organization feature flags", error)) .subscribeOn(LoadShifter.elasticScheduler) .subscribe(); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java index b60a7faae798..80cc7ae6827d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/UserSignupCEImpl.java @@ -4,8 +4,8 @@ import com.appsmith.server.authentication.handlers.AuthenticationSuccessHandler; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.LoginSource; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; import com.appsmith.server.domains.UserState; @@ -20,7 +20,7 @@ import com.appsmith.server.services.CaptchaService; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.EmailService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import com.appsmith.server.solutions.EnvManager; @@ -59,9 +59,9 @@ import static com.appsmith.server.constants.ce.FieldNameCE.DEFAULT; import static com.appsmith.server.constants.ce.FieldNameCE.EMAIL; import static com.appsmith.server.constants.ce.FieldNameCE.NAME; +import static com.appsmith.server.constants.ce.FieldNameCE.ORGANIZATION; import static com.appsmith.server.constants.ce.FieldNameCE.PROFICIENCY; import static com.appsmith.server.constants.ce.FieldNameCE.ROLE; -import static com.appsmith.server.constants.ce.FieldNameCE.TENANT; import static com.appsmith.server.helpers.RedirectHelper.REDIRECT_URL_QUERY_PARAM; import static com.appsmith.server.helpers.ValidationUtils.LOGIN_PASSWORD_MAX_LENGTH; import static com.appsmith.server.helpers.ValidationUtils.LOGIN_PASSWORD_MIN_LENGTH; @@ -82,7 +82,7 @@ public class UserSignupCEImpl implements UserSignupCE { private final UserUtils userUtils; private final NetworkUtils networkUtils; private final EmailService emailService; - private final TenantService tenantService; + private final OrganizationService organizationService; private static final ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy(); @@ -99,7 +99,7 @@ public UserSignupCEImpl( UserUtils userUtils, NetworkUtils networkUtils, EmailService emailService, - TenantService tenantService) { + OrganizationService organizationService) { this.userService = userService; this.userDataService = userDataService; @@ -111,7 +111,7 @@ public UserSignupCEImpl( this.userUtils = userUtils; this.networkUtils = networkUtils; this.emailService = emailService; - this.tenantService = tenantService; + this.organizationService = organizationService; } /** @@ -130,16 +130,17 @@ public Mono signupAndLogin(User user, ServerWebExchange exchange) { return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, EMAIL)); } - Mono tenantMono = tenantService - .getDefaultTenant() - .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, DEFAULT, TENANT))); + Mono organizationMono = organizationService + .getDefaultOrganization() + .switchIfEmpty( + Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, DEFAULT, ORGANIZATION))); - // - Only creating user if the password strength is acceptable as per the tenant policy + // - Only creating user if the password strength is acceptable as per the organization policy // - Welcome email will be sent post user email verification - Mono createUserMono = tenantMono.flatMap(tenant -> { - TenantConfiguration tenantConfiguration = tenant.getTenantConfiguration(); - boolean isStrongPasswordPolicyEnabled = tenantConfiguration != null - && Boolean.TRUE.equals(tenantConfiguration.getIsStrongPasswordPolicyEnabled()); + Mono createUserMono = organizationMono.flatMap(organization -> { + OrganizationConfiguration organizationConfiguration = organization.getOrganizationConfiguration(); + boolean isStrongPasswordPolicyEnabled = organizationConfiguration != null + && Boolean.TRUE.equals(organizationConfiguration.getIsStrongPasswordPolicyEnabled()); if (!validateUserPassword(user.getPassword(), isStrongPasswordPolicyEnabled)) { return isStrongPasswordPolicyEnabled diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java index 2158670c2b2d..49c8607bc577 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java @@ -37,12 +37,12 @@ class FeatureFlaggedMethodInvokerAspectTest { @BeforeEach void setUp() { - Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.TENANT_TEST_FEATURE))) + Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE))) .thenReturn(Mono.just(false)); CachedFeatures cachedFeatures = new CachedFeatures(); - cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.TENANT_TEST_FEATURE.name(), Boolean.FALSE)); - Mockito.when(featureFlagService.getCachedTenantFeatureFlags()).thenReturn(cachedFeatures); + cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.FALSE)); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); } @Test @@ -53,7 +53,7 @@ void testEEOnlyMethod() { @Test void eeCeCompatibleDiffMethod_eeImplTest() { - Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.TENANT_TEST_FEATURE))) + Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE))) .thenReturn(Mono.just(true)); Mono resultMono = testComponent.eeCeCompatibleDiffMethod(); StepVerifier.create(resultMono).expectNext(EE_RESPONSE).verifyComplete(); @@ -86,7 +86,7 @@ void ceEeDiffMethod_ceImplTest() { @Test void ceEeDiffMethod_eeImplTest() { - Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.TENANT_TEST_FEATURE))) + Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE))) .thenReturn(Mono.just(true)); Mono resultMono = testComponent.ceEeDiffMethod(); StepVerifier.create(resultMono).expectNext(EE_RESPONSE).verifyComplete(); @@ -94,7 +94,7 @@ void ceEeDiffMethod_eeImplTest() { @Test void ceEeDiffMethodReturnsFlux_eeImplTest() { - Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.TENANT_TEST_FEATURE))) + Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE))) .thenReturn(Mono.just(true)); Flux resultFlux = testComponent.ceEeDiffMethodReturnsFlux(); StepVerifier.create(resultFlux).expectNext("ee", "impl", "method").verifyComplete(); @@ -109,8 +109,8 @@ void ceEeDiffMethodReturnsFlux_ceImplTest() { @Test void ceEeSyncMethod_eeImplTest() { CachedFeatures cachedFeatures = new CachedFeatures(); - cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.TENANT_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedTenantFeatureFlags()).thenReturn(cachedFeatures); + cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); String result = testComponent.ceEeSyncMethod("arg_"); assertEquals("arg_ee_impl_method", result); } @@ -124,8 +124,8 @@ void ceEeSyncMethod_ceImplTest() { @Test void ceEeThrowAppsmithException_eeImplTest() { CachedFeatures cachedFeatures = new CachedFeatures(); - cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.TENANT_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedTenantFeatureFlags()).thenReturn(cachedFeatures); + cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); assertThrows( AppsmithException.class, () -> testComponent.ceEeThrowAppsmithException("arg_"), @@ -135,8 +135,8 @@ void ceEeThrowAppsmithException_eeImplTest() { @Test void ceEeThrowNonAppsmithException_eeImplTest_throwExceptionFromAspect() { CachedFeatures cachedFeatures = new CachedFeatures(); - cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.TENANT_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedTenantFeatureFlags()).thenReturn(cachedFeatures); + cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); assertThrows( AppsmithException.class, () -> testComponent.ceEeThrowNonAppsmithException("arg_"), diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java index 3da1b574d1c0..373e0eabf195 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java @@ -19,19 +19,19 @@ public Mono eeOnlyMethod() { return Mono.just("ee_impl_method"); } - @FeatureFlagged(featureFlagName = FeatureFlagEnum.TENANT_TEST_FEATURE) + @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) @Override public Mono ceEeDiffMethod() { return Mono.just("ee_impl_method"); } - @FeatureFlagged(featureFlagName = FeatureFlagEnum.TENANT_TEST_FEATURE) + @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) @Override public Mono eeCeCompatibleDiffMethod() { return Mono.just("ee_impl_method"); } - @FeatureFlagged(featureFlagName = FeatureFlagEnum.TENANT_TEST_FEATURE) + @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) @Override public Flux ceEeDiffMethodReturnsFlux() { List result = List.of("ee", "impl", "method"); @@ -39,19 +39,19 @@ public Flux ceEeDiffMethodReturnsFlux() { } @Override - @FeatureFlagged(featureFlagName = FeatureFlagEnum.TENANT_TEST_FEATURE) + @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) public String ceEeSyncMethod(String arg) { return arg + "ee_impl_method"; } @Override - @FeatureFlagged(featureFlagName = FeatureFlagEnum.TENANT_TEST_FEATURE) + @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) public void ceEeThrowAppsmithException(String arg) { throw new AppsmithException(AppsmithError.GENERIC_BAD_REQUEST, "This is a test exception"); } @Override - @FeatureFlagged(featureFlagName = FeatureFlagEnum.TENANT_TEST_FEATURE) + @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) public void ceEeThrowNonAppsmithException(String arg) { throw new RuntimeException("This is a test exception"); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java index 98b1dbd01151..8fec8a1f87ba 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java @@ -2,16 +2,16 @@ import com.appsmith.external.models.PluginType; import com.appsmith.external.models.Policy; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.PermissionGroup; import com.appsmith.server.domains.Plugin; import com.appsmith.server.domains.PricingPlan; -import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserState; import com.appsmith.server.dtos.Permission; +import com.appsmith.server.repositories.OrganizationRepository; import com.appsmith.server.repositories.PermissionGroupRepository; import com.appsmith.server.repositories.PluginRepository; -import com.appsmith.server.repositories.TenantRepository; import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.repositories.WorkspaceRepository; import com.appsmith.server.solutions.PolicySolution; @@ -40,7 +40,7 @@ ApplicationRunner init( UserRepository userRepository, WorkspaceRepository workspaceRepository, PluginRepository pluginRepository, - TenantRepository tenantRepository, + OrganizationRepository organizationRepository, PermissionGroupRepository permissionGroupRepository, PolicySolution policySolution) { @@ -117,29 +117,29 @@ ApplicationRunner init( }) .flatMap(pluginRepository::save); - Tenant defaultTenant = new Tenant(); - defaultTenant.setDisplayName("Default"); - defaultTenant.setSlug("default"); - defaultTenant.setPricingPlan(PricingPlan.FREE); + Organization defaultOrganization = new Organization(); + defaultOrganization.setDisplayName("Default"); + defaultOrganization.setSlug("default"); + defaultOrganization.setPricingPlan(PricingPlan.FREE); - Mono defaultTenantId = tenantRepository + Mono defaultOrganizationId = organizationRepository .findBySlug("default") - .switchIfEmpty(tenantRepository.save(defaultTenant)) - .map(Tenant::getId) + .switchIfEmpty(organizationRepository.save(defaultOrganization)) + .map(Organization::getId) .cache(); Flux userFlux = Flux.just(userData) - .zipWith(defaultTenantId.repeat()) + .zipWith(defaultOrganizationId.repeat()) .flatMap(tuple -> { Object[] array = tuple.getT1(); - String tenantId = tuple.getT2(); + String organizationId = tuple.getT2(); log.debug("Going to create bare users"); User user = new User(); user.setName((String) array[0]); user.setEmail((String) array[1]); user.setState((UserState) array[2]); user.setPolicies((Set) array[3]); - user.setTenantId(tenantId); + user.setOrganizationId(organizationId); return userRepository.save(user); }) .flatMap(user -> { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java index 09c30c0d6dab..8f169f59862a 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java @@ -21,6 +21,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.http.MediaType; import org.springframework.http.client.MultipartBodyBuilder; +import org.springframework.http.codec.multipart.Part; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.reactive.function.BodyInserters; @@ -29,6 +30,7 @@ import java.io.IOException; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; @SpringBootTest @AutoConfigureWebTestClient @@ -69,7 +71,7 @@ private MultipartBodyBuilder createBodyBuilder(String fileName) throws IOExcepti @WithMockUser public void whenFileUploadedWithLongHeader_thenVerifyErrorStatus() throws IOException { - Mockito.when(importService.extractArtifactExchangeJsonAndSaveArtifact(any(), any(), any())) + Mockito.when(importService.extractArtifactExchangeJsonAndSaveArtifact(anyString(), any(), any())) .thenAnswer(importableArtifactDTOAnswer(new ApplicationImportDTO())); final String fileName = getFileName(130 * 1024); @@ -100,7 +102,7 @@ public void whenFileUploadedWithLongHeader_thenVerifyErrorStatus() throws IOExce @WithMockUser public void whenFileUploadedWithShortHeader_thenVerifySuccessStatus() throws IOException { - Mockito.when(importService.extractArtifactExchangeJsonAndSaveArtifact(any(), any(), any())) + Mockito.when(importService.extractArtifactExchangeJsonAndSaveArtifact(any(Part.class), any(), any())) .thenAnswer(importableArtifactDTOAnswer(new ApplicationImportDTO())); final String fileName = getFileName(2 * 1024); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/domains/EqualityTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/domains/EqualityTest.java index ff0476e4cbed..9068612b2659 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/domains/EqualityTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/domains/EqualityTest.java @@ -19,6 +19,7 @@ public class EqualityTest { private final Set> TESTED_CLASSES = Set.of( // Note: Adding a class here means that we have a test for its equality in this file. ApplicationDetail.class, + OrganizationConfiguration.class, TenantConfiguration.class, Application.AppLayout.class, Application.EmbedSetting.class, @@ -50,12 +51,12 @@ void testAffirmation() { } @Test - void testTenantConfiguration() { - TenantConfiguration c1 = new TenantConfiguration(); + void testOrganizationConfiguration() { + OrganizationConfiguration c1 = new OrganizationConfiguration(); c1.setEmailVerificationEnabled(true); - TenantConfiguration c2 = new TenantConfiguration(); + OrganizationConfiguration c2 = new OrganizationConfiguration(); c2.setEmailVerificationEnabled(true); - TenantConfiguration c3 = new TenantConfiguration(); + OrganizationConfiguration c3 = new OrganizationConfiguration(); c3.setEmailVerificationEnabled(false); assertThat(c1).isEqualTo(c2).isNotEqualTo(c3); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java index 8dffa584818f..490eaea37782 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java @@ -27,6 +27,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; @@ -41,20 +42,16 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; -import org.springframework.http.MediaType; -import org.springframework.http.codec.multipart.FilePart; +import org.springframework.core.io.DefaultResourceLoader; import org.springframework.security.test.context.support.WithUserDetails; import org.springframework.test.annotation.DirtiesContext; -import reactor.core.publisher.Flux; +import org.springframework.util.StreamUtils; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.io.IOException; import java.net.URISyntaxException; -import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Instant; @@ -228,13 +225,13 @@ public void verifyAssertions( @WithUserDetails(value = "api_user") public void importApplication_ThenExportApplication_MatchJson_equals_Success() throws URISyntaxException { String filePath = "ce-automation-test.json"; - FilePart filePart = createFilePart(filePath); + String jsonContents = readResource(filePath); Workspace newWorkspace = new Workspace(); newWorkspace.setName("Template Workspace"); Mono workspaceMono = workspaceService.create(newWorkspace).cache(); ApplicationJson applicationJsonToBeImported = importService - .extractArtifactExchangeJson(filePart) + .extractArtifactExchangeJson(jsonContents) .map(artifactExchangeJson -> (ApplicationJson) artifactExchangeJson) .block(); @@ -249,7 +246,7 @@ public void importApplication_ThenExportApplication_MatchJson_equals_Success() t final Mono resultMono = workspaceMono .flatMap(workspace -> - importService.extractArtifactExchangeJsonAndSaveArtifact(filePart, workspace.getId(), null)) + importService.extractArtifactExchangeJsonAndSaveArtifact(jsonContents, workspace.getId(), null)) .map(importableArtifactDTO -> (ApplicationImportDTO) importableArtifactDTO); final Mono exportApplicationMono = resultMono.flatMap(applicationImportDTO -> { @@ -280,17 +277,10 @@ public void importApplication_ThenExportApplication_MatchJson_equals_Success() t .verifyComplete(); } - private FilePart createFilePart(String filePath) throws URISyntaxException { - FilePart filePart = Mockito.mock(FilePart.class, Mockito.RETURNS_DEEP_STUBS); - URL resource = this.getClass().getResource(filePath); - Flux dataBufferFlux = DataBufferUtils.read( - Path.of(resource.toURI()), new DefaultDataBufferFactory(), 4096) - .cache(); - - Mockito.when(filePart.content()).thenReturn(dataBufferFlux); - Mockito.when(filePart.headers().getContentType()).thenReturn(MediaType.APPLICATION_JSON); - - return filePart; + @SneakyThrows + private String readResource(String filePath) { + return StreamUtils.copyToString( + new DefaultResourceLoader().getResource(filePath).getInputStream(), StandardCharsets.UTF_8); } private void removeCustomJsLibsEntries(JsonObject applicationObjectNode) { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/resourcemap/ExchangeJsonConversionTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/resourcemap/ExchangeJsonConversionTests.java index 9dfe3997401d..c42f8e4c3cce 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/resourcemap/ExchangeJsonConversionTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/resourcemap/ExchangeJsonConversionTests.java @@ -1,6 +1,6 @@ package com.appsmith.server.git.resourcemap; -import com.appsmith.external.git.GitExecutor; +import com.appsmith.external.git.handler.FSGitHandler; import com.appsmith.external.git.models.GitResourceIdentity; import com.appsmith.external.git.models.GitResourceMap; import com.appsmith.server.constants.ArtifactType; @@ -52,7 +52,7 @@ public class ExchangeJsonConversionTests { CommonGitFileUtils commonGitFileUtils; @SpyBean - GitExecutor gitExecutor; + FSGitHandler fsGitHandler; @TestTemplate public void testConvertArtifactJsonToGitResourceMap_whenArtifactIsFullyPopulated_returnsCorrespondingResourceMap( @@ -127,7 +127,7 @@ public void testSerializeArtifactExchangeJson_whenArtifactIsFullyPopulated_retur ExchangeJsonContext context) throws IOException, GitAPIException { ArtifactExchangeJson originalArtifactJson = createArtifactJson(context).block(); - Mockito.doReturn(Mono.just(true)).when(gitExecutor).resetToLastCommit(Mockito.any(), Mockito.anyString()); + Mockito.doReturn(Mono.just(true)).when(fsGitHandler).resetToLastCommit(Mockito.any(), Mockito.anyString()); Files.createDirectories(Path.of("./container-volumes/git-storage/test123")); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java index f9553860e6d0..b55cfc9b9b53 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java @@ -2,8 +2,8 @@ import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.services.CacheableFeatureFlagHelper; import org.junit.jupiter.api.BeforeEach; @@ -21,7 +21,7 @@ import java.util.Map; import java.util.UUID; -import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; +import static com.appsmith.external.enums.FeatureFlagEnum.ORGANIZATION_TEST_FEATURE; import static com.appsmith.server.constants.FeatureMigrationType.DISABLE; import static com.appsmith.server.constants.FeatureMigrationType.ENABLE; import static com.appsmith.server.constants.MigrationStatus.PENDING; @@ -42,37 +42,37 @@ void setUp() {} @Test void getUpdatedFlagsWithPendingMigration_diffForExistingAndLatestFlag_pendingMigrationReportedWithDisableStatus() { - Tenant defaultTenant = new Tenant(); - defaultTenant.setId(UUID.randomUUID().toString()); - defaultTenant.setTenantConfiguration(new TenantConfiguration()); + Organization defaultOrganization = new Organization(); + defaultOrganization.setId(UUID.randomUUID().toString()); + defaultOrganization.setOrganizationConfiguration(new OrganizationConfiguration()); CachedFeatures existingCachedFeatures = new CachedFeatures(); Map featureMap = new HashMap<>(); - featureMap.put(TENANT_TEST_FEATURE.name(), true); + featureMap.put(ORGANIZATION_TEST_FEATURE.name(), true); existingCachedFeatures.setFeatures(featureMap); existingCachedFeatures.setRefreshedAt(Instant.now().minus(1, ChronoUnit.DAYS)); CachedFeatures latestCachedFeatures = new CachedFeatures(); Map latestFeatureMap = new HashMap<>(); - latestFeatureMap.put(TENANT_TEST_FEATURE.name(), false); + latestFeatureMap.put(ORGANIZATION_TEST_FEATURE.name(), false); latestCachedFeatures.setFeatures(latestFeatureMap); latestCachedFeatures.setRefreshedAt(Instant.now()); - Mockito.when(cacheableFeatureFlagHelper.fetchCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(any())) .thenReturn(Mono.just(existingCachedFeatures)) .thenReturn(Mono.just(latestCachedFeatures)); - Mockito.when(cacheableFeatureFlagHelper.evictCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.evictCachedOrganizationFeatures(any())) .thenReturn(Mono.empty()); Mono> getUpdatedFlagsWithPendingMigration = - featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultTenant); + featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultOrganization); StepVerifier.create(getUpdatedFlagsWithPendingMigration) .assertNext(featureFlagEnumFeatureMigrationTypeMap -> { assertThat(featureFlagEnumFeatureMigrationTypeMap).isNotEmpty(); assertThat(featureFlagEnumFeatureMigrationTypeMap).hasSize(1); - assertThat(featureFlagEnumFeatureMigrationTypeMap.get(TENANT_TEST_FEATURE)) + assertThat(featureFlagEnumFeatureMigrationTypeMap.get(ORGANIZATION_TEST_FEATURE)) .isEqualTo(DISABLE); }) .verifyComplete(); @@ -80,37 +80,37 @@ void getUpdatedFlagsWithPendingMigration_diffForExistingAndLatestFlag_pendingMig @Test void getUpdatedFlagsWithPendingMigration_diffForExistingAndLatestFlag_pendingMigrationReportedWithEnableStatus() { - Tenant defaultTenant = new Tenant(); - defaultTenant.setId(UUID.randomUUID().toString()); - defaultTenant.setTenantConfiguration(new TenantConfiguration()); + Organization defaultOrganization = new Organization(); + defaultOrganization.setId(UUID.randomUUID().toString()); + defaultOrganization.setOrganizationConfiguration(new OrganizationConfiguration()); CachedFeatures existingCachedFeatures = new CachedFeatures(); Map featureMap = new HashMap<>(); - featureMap.put(TENANT_TEST_FEATURE.name(), false); + featureMap.put(ORGANIZATION_TEST_FEATURE.name(), false); existingCachedFeatures.setFeatures(featureMap); existingCachedFeatures.setRefreshedAt(Instant.now().minus(1, ChronoUnit.DAYS)); CachedFeatures latestCachedFeatures = new CachedFeatures(); Map latestFeatureMap = new HashMap<>(); - latestFeatureMap.put(TENANT_TEST_FEATURE.name(), true); + latestFeatureMap.put(ORGANIZATION_TEST_FEATURE.name(), true); latestCachedFeatures.setFeatures(latestFeatureMap); latestCachedFeatures.setRefreshedAt(Instant.now()); - Mockito.when(cacheableFeatureFlagHelper.fetchCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(any())) .thenReturn(Mono.just(existingCachedFeatures)) .thenReturn(Mono.just(latestCachedFeatures)); - Mockito.when(cacheableFeatureFlagHelper.evictCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.evictCachedOrganizationFeatures(any())) .thenReturn(Mono.empty()); Mono> getUpdatedFlagsWithPendingMigration = - featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultTenant); + featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultOrganization); StepVerifier.create(getUpdatedFlagsWithPendingMigration) .assertNext(featureFlagEnumFeatureMigrationTypeMap -> { assertThat(featureFlagEnumFeatureMigrationTypeMap).isNotEmpty(); assertThat(featureFlagEnumFeatureMigrationTypeMap).hasSize(1); - assertThat(featureFlagEnumFeatureMigrationTypeMap.get(TENANT_TEST_FEATURE)) + assertThat(featureFlagEnumFeatureMigrationTypeMap.get(ORGANIZATION_TEST_FEATURE)) .isEqualTo(ENABLE); }) .verifyComplete(); @@ -118,24 +118,24 @@ void getUpdatedFlagsWithPendingMigration_diffForExistingAndLatestFlag_pendingMig @Test void getUpdatedFlagsWithPendingMigration_noDiffForExistingAndLatestFlag_noPendingMigrations() { - Tenant defaultTenant = new Tenant(); - defaultTenant.setId(UUID.randomUUID().toString()); - defaultTenant.setTenantConfiguration(new TenantConfiguration()); + Organization defaultOrganization = new Organization(); + defaultOrganization.setId(UUID.randomUUID().toString()); + defaultOrganization.setOrganizationConfiguration(new OrganizationConfiguration()); CachedFeatures existingCachedFeatures = new CachedFeatures(); Map featureMap = new HashMap<>(); - featureMap.put(TENANT_TEST_FEATURE.name(), true); + featureMap.put(ORGANIZATION_TEST_FEATURE.name(), true); existingCachedFeatures.setFeatures(featureMap); existingCachedFeatures.setRefreshedAt(Instant.now().minus(1, ChronoUnit.HOURS)); - Mockito.when(cacheableFeatureFlagHelper.fetchCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(any())) .thenReturn(Mono.just(existingCachedFeatures)); - Mockito.when(cacheableFeatureFlagHelper.evictCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.evictCachedOrganizationFeatures(any())) .thenReturn(Mono.empty()); Mono> getUpdatedFlagsWithPendingMigration = - featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultTenant); + featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultOrganization); StepVerifier.create(getUpdatedFlagsWithPendingMigration) .assertNext(featureFlagEnumFeatureMigrationTypeMap -> { @@ -147,14 +147,14 @@ void getUpdatedFlagsWithPendingMigration_noDiffForExistingAndLatestFlag_noPendin } @Test - void getUpdatedFlagsWithPendingMigration_fetchTenantFlagsFailedFromCS_pendingMigrationReported() { - Tenant defaultTenant = new Tenant(); - defaultTenant.setId(UUID.randomUUID().toString()); - defaultTenant.setTenantConfiguration(new TenantConfiguration()); + void getUpdatedFlagsWithPendingMigration_fetchOrganizationFlagsFailedFromCS_pendingMigrationReported() { + Organization defaultOrganization = new Organization(); + defaultOrganization.setId(UUID.randomUUID().toString()); + defaultOrganization.setOrganizationConfiguration(new OrganizationConfiguration()); CachedFeatures existingCachedFeatures = new CachedFeatures(); Map featureMap = new HashMap<>(); - featureMap.put(TENANT_TEST_FEATURE.name(), true); + featureMap.put(ORGANIZATION_TEST_FEATURE.name(), true); existingCachedFeatures.setFeatures(featureMap); existingCachedFeatures.setRefreshedAt(Instant.now().minus(1, ChronoUnit.HOURS)); @@ -162,18 +162,18 @@ void getUpdatedFlagsWithPendingMigration_fetchTenantFlagsFailedFromCS_pendingMig existingCachedFeatures.setFeatures(new HashMap<>()); existingCachedFeatures.setRefreshedAt(Instant.now()); - Mockito.when(cacheableFeatureFlagHelper.fetchCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(any())) .thenReturn(Mono.just(existingCachedFeatures)) .thenReturn(Mono.just(latestCachedFeatures)); - Mockito.when(cacheableFeatureFlagHelper.updateCachedTenantFeatures(any(), any())) + Mockito.when(cacheableFeatureFlagHelper.updateCachedOrganizationFeatures(any(), any())) .thenReturn(Mono.just(existingCachedFeatures)); - Mockito.when(cacheableFeatureFlagHelper.evictCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.evictCachedOrganizationFeatures(any())) .thenReturn(Mono.empty()); Mono> getUpdatedFlagsWithPendingMigration = - featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultTenant); + featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultOrganization); StepVerifier.create(getUpdatedFlagsWithPendingMigration) .assertNext(featureFlagEnumFeatureMigrationTypeMap -> { @@ -186,9 +186,9 @@ void getUpdatedFlagsWithPendingMigration_fetchTenantFlagsFailedFromCS_pendingMig @Test void checkAndExecuteMigrationsForFeatureFlag_nullFeatureFlag_success() { - Tenant defaultTenant = new Tenant(); + Organization defaultOrganization = new Organization(); Mono resultMono = - featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(defaultTenant, null); + featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(defaultOrganization, null); StepVerifier.create(resultMono) .assertNext(result -> assertThat(result).isTrue()) .verifyComplete(); @@ -196,28 +196,28 @@ void checkAndExecuteMigrationsForFeatureFlag_nullFeatureFlag_success() { @Test void checkAndExecuteMigrationsForFeatureFlag_validFeatureFlag_success() { - Tenant defaultTenant = new Tenant(); - TenantConfiguration tenantConfiguration = new TenantConfiguration(); - tenantConfiguration.setFeaturesWithPendingMigration(Map.of(TENANT_TEST_FEATURE, ENABLE)); - tenantConfiguration.setMigrationStatus(PENDING); - defaultTenant.setTenantConfiguration(tenantConfiguration); + Organization defaultOrganization = new Organization(); + OrganizationConfiguration organizationConfiguration = new OrganizationConfiguration(); + organizationConfiguration.setFeaturesWithPendingMigration(Map.of(ORGANIZATION_TEST_FEATURE, ENABLE)); + organizationConfiguration.setMigrationStatus(PENDING); + defaultOrganization.setOrganizationConfiguration(organizationConfiguration); CachedFeatures existingCachedFeatures = new CachedFeatures(); Map featureMap = new HashMap<>(); - featureMap.put(TENANT_TEST_FEATURE.name(), true); + featureMap.put(ORGANIZATION_TEST_FEATURE.name(), true); existingCachedFeatures.setFeatures(featureMap); existingCachedFeatures.setRefreshedAt(Instant.now().minus(1, ChronoUnit.HOURS)); - Mockito.when(cacheableFeatureFlagHelper.fetchCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(any())) .thenReturn(Mono.just(existingCachedFeatures)); - Mono resultMono = - featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(defaultTenant, TENANT_TEST_FEATURE); + Mono resultMono = featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag( + defaultOrganization, ORGANIZATION_TEST_FEATURE); StepVerifier.create(resultMono) .assertNext(result -> { assertThat(result).isTrue(); - assertThat(tenantConfiguration.getFeaturesWithPendingMigration()) + assertThat(organizationConfiguration.getFeaturesWithPendingMigration()) .hasSize(1); - assertThat(tenantConfiguration.getMigrationStatus()).isEqualTo(PENDING); + assertThat(organizationConfiguration.getMigrationStatus()).isEqualTo(PENDING); }) .verifyComplete(); } @@ -228,36 +228,36 @@ void checkAndExecuteMigrationsForFeatureFlag_validFeatureFlag_success() { // Mock DB state to have the feature flag in pending migration list with DISABLE status which means the feature // flag flipped from true to false - Tenant defaultTenant = new Tenant(); - defaultTenant.setId(UUID.randomUUID().toString()); - TenantConfiguration tenantConfiguration = new TenantConfiguration(); - tenantConfiguration.setFeaturesWithPendingMigration(Map.of(TENANT_TEST_FEATURE, DISABLE)); - defaultTenant.setTenantConfiguration(tenantConfiguration); + Organization defaultOrganization = new Organization(); + defaultOrganization.setId(UUID.randomUUID().toString()); + OrganizationConfiguration organizationConfiguration = new OrganizationConfiguration(); + organizationConfiguration.setFeaturesWithPendingMigration(Map.of(ORGANIZATION_TEST_FEATURE, DISABLE)); + defaultOrganization.setOrganizationConfiguration(organizationConfiguration); // Mock CS calls to fetch the feature flags to have the feature flag in pending migration list with ENABLE // status // This means the feature flag flipped from false to true again with latest check CachedFeatures existingCachedFeatures = new CachedFeatures(); Map featureMap = new HashMap<>(); - featureMap.put(TENANT_TEST_FEATURE.name(), false); + featureMap.put(ORGANIZATION_TEST_FEATURE.name(), false); existingCachedFeatures.setFeatures(featureMap); existingCachedFeatures.setRefreshedAt(Instant.now().minus(1, ChronoUnit.DAYS)); CachedFeatures latestCachedFeatures = new CachedFeatures(); Map latestFeatureMap = new HashMap<>(); - latestFeatureMap.put(TENANT_TEST_FEATURE.name(), true); + latestFeatureMap.put(ORGANIZATION_TEST_FEATURE.name(), true); latestCachedFeatures.setFeatures(latestFeatureMap); latestCachedFeatures.setRefreshedAt(Instant.now()); - Mockito.when(cacheableFeatureFlagHelper.fetchCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(any())) .thenReturn(Mono.just(existingCachedFeatures)) .thenReturn(Mono.just(latestCachedFeatures)); - Mockito.when(cacheableFeatureFlagHelper.evictCachedTenantFeatures(any())) + Mockito.when(cacheableFeatureFlagHelper.evictCachedOrganizationFeatures(any())) .thenReturn(Mono.empty()); Mono> getUpdatedFlagsWithPendingMigration = - featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultTenant); + featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(defaultOrganization); StepVerifier.create(getUpdatedFlagsWithPendingMigration) .assertNext(featureFlagEnumFeatureMigrationTypeMap -> { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java index 8e4199ba0bc5..689257da3700 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java @@ -17,7 +17,7 @@ import java.util.HashMap; import java.util.Map; -import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; +import static com.appsmith.external.enums.FeatureFlagEnum.ORGANIZATION_TEST_FEATURE; import static com.appsmith.external.enums.FeatureFlagEnum.TEST_FEATURE_1; import static com.appsmith.external.enums.FeatureFlagEnum.TEST_FEATURE_2; @@ -50,10 +50,10 @@ public Mono evictUserCachedFlags(String userIdentifier) { return Mono.empty(); } - @Cache(cacheName = "tenantNewFeatures", key = "{#tenantId}") + @Cache(cacheName = "organizationNewFeatures", key = "{#organizationId}") @Override - public Mono fetchCachedTenantFeatures(String tenantId) { - return getRemoteFeaturesForTenant(new FeaturesRequestDTO()).map(responseDTO -> { + public Mono fetchCachedOrganizationFeatures(String organizationId) { + return getRemoteFeaturesForOrganization(new FeaturesRequestDTO()).map(responseDTO -> { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setRefreshedAt(Instant.now()); cachedFeatures.setFeatures(responseDTO.getFeatures()); @@ -61,23 +61,23 @@ public Mono fetchCachedTenantFeatures(String tenantId) { }); } - @Cache(cacheName = "tenantNewFeatures", key = "{#tenantId}") + @Cache(cacheName = "organizationNewFeatures", key = "{#organizationId}") @Override - public Mono updateCachedTenantFeatures(String tenantId, CachedFeatures cachedFeatures) { + public Mono updateCachedOrganizationFeatures(String organizationId, CachedFeatures cachedFeatures) { return Mono.just(cachedFeatures); } - @CacheEvict(cacheName = "tenantNewFeatures", key = "{#tenantId}") + @CacheEvict(cacheName = "organizationNewFeatures", key = "{#organizationId}") @Override - public Mono evictCachedTenantFeatures(String tenantId) { + public Mono evictCachedOrganizationFeatures(String organizationId) { return Mono.empty(); } @Override - public Mono getRemoteFeaturesForTenant(FeaturesRequestDTO featuresRequestDTO) { + public Mono getRemoteFeaturesForOrganization(FeaturesRequestDTO featuresRequestDTO) { FeaturesResponseDTO responseDTO = new FeaturesResponseDTO(); Map features = new HashMap<>(); - features.put(TENANT_TEST_FEATURE.name(), true); + features.put(ORGANIZATION_TEST_FEATURE.name(), true); responseDTO.setFeatures(features); return Mono.just(responseDTO); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java index b4d3e67c91c7..e10befb4c39a 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java @@ -1,7 +1,7 @@ package com.appsmith.server.helpers.ce; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.services.OrganizationService; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -19,7 +19,6 @@ import static com.appsmith.server.constants.ce.EmailConstantsCE.INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE; import static com.appsmith.server.constants.ce.EmailConstantsCE.INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; @SpringBootTest class EmailServiceHelperCETest { @@ -28,14 +27,15 @@ class EmailServiceHelperCETest { @Qualifier("emailServiceHelperCEImpl") private EmailServiceHelperCE emailServiceHelperCE; @Autowired - TenantService tenantService; + OrganizationService organizationService; @Test @WithUserDetails(value = "api_user") public void testEnrichWithBrandParams() { - Tenant defautTenant = tenantService.getTenantConfiguration().block(); - String instanceName = - StringUtils.defaultIfEmpty(defautTenant.getTenantConfiguration().getInstanceName(), "Appsmith"); + Organization defautOrganization = + organizationService.getOrganizationConfiguration().block(); + String instanceName = StringUtils.defaultIfEmpty( + defautOrganization.getOrganizationConfiguration().getInstanceName(), "Appsmith"); StepVerifier.create(emailServiceHelperCE.enrichWithBrandParams(new HashMap<>(), "www.test.com")) .assertNext(map -> { assertThat(map.containsKey(INSTANCE_NAME)).isTrue(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java index 1ac66965af93..317f121db519 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java @@ -78,6 +78,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; @@ -93,6 +94,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; @@ -102,6 +104,7 @@ import org.springframework.security.test.context.support.WithUserDetails; import org.springframework.test.annotation.DirtiesContext; import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.StreamUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -110,6 +113,7 @@ import java.net.URISyntaxException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.time.Duration; import java.time.Instant; @@ -859,10 +863,8 @@ public void importArtifactFromInvalidFileTest() { @Test @WithUserDetails(value = "api_user") public void importArtifactWithNullWorkspaceIdTest() { - FilePart filepart = Mockito.mock(FilePart.class, Mockito.RETURNS_DEEP_STUBS); - Mono resultMono = - importService.extractArtifactExchangeJsonAndSaveArtifact(filepart, null, null); + importService.extractArtifactExchangeJsonAndSaveArtifact("", null, null); StepVerifier.create(resultMono) .expectErrorMatches(throwable -> throwable instanceof AppsmithException @@ -4943,9 +4945,10 @@ public void mergeApplicationJsonWithApplication_WhenNoPermissionToCreatePage_Fai return applicationRepository.save(application); }) .flatMap(application -> { - FilePart filePart = createFilePart("test_assets/ImportExportServiceTest/valid-application.json"); + final String validAppJsonContents = + readResource("test_assets/ImportExportServiceTest/valid-application.json"); return importService - .extractArtifactExchangeJson(filePart) + .extractArtifactExchangeJson(validAppJsonContents) .map(artifactExchangeJson -> (ApplicationJson) artifactExchangeJson) .flatMap(applicationJson -> importService.mergeArtifactExchangeJsonWithImportableArtifact( workspaceId, application.getId(), null, applicationJson, null)) @@ -4957,6 +4960,12 @@ public void mergeApplicationJsonWithApplication_WhenNoPermissionToCreatePage_Fai .verify(); } + @SneakyThrows + private String readResource(String filePath) { + return StreamUtils.copyToString( + new DefaultResourceLoader().getResource(filePath).getInputStream(), StandardCharsets.UTF_8); + } + @Test @WithUserDetails(value = "api_user") public void extractFileAndUpdateNonGitConnectedApplication_WhenNoPermissionToCreatePage_Fails() { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UsagePulseServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UsagePulseServiceTest.java index 517b3ceeadb2..4a502d82bba9 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UsagePulseServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UsagePulseServiceTest.java @@ -57,7 +57,7 @@ public void test_AnonymousUserPulse_Success() { assertThat(usagePulse.getUser()).isEqualTo(anonymousUserId); assertThat(usagePulse.getIsAnonymousUser()).isTrue(); assertThat(usagePulse.getInstanceId()).isNotNull(); - assertThat(usagePulse.getTenantId()).isNotNull(); + assertThat(usagePulse.getOrganizationId()).isNotNull(); assertThat(usagePulse.getViewMode()).isTrue(); }) .verifyComplete(); @@ -94,7 +94,7 @@ public void test_loggedInUserPulse_Success() { assertThat(usagePulse.getUser()).isEqualTo(hashedUserEmail); assertThat(usagePulse.getIsAnonymousUser()).isFalse(); assertThat(usagePulse.getInstanceId()).isNotNull(); - assertThat(usagePulse.getTenantId()).isNotNull(); + assertThat(usagePulse.getOrganizationId()).isNotNull(); assertThat(usagePulse.getViewMode()).isTrue(); }) .verifyComplete(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserServiceTest.java index 7edad2e12835..3f9aad56b434 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserServiceTest.java @@ -7,10 +7,10 @@ import com.appsmith.server.configurations.WithMockAppsmithUser; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.LoginSource; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.PasswordResetToken; import com.appsmith.server.domains.PermissionGroup; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; import com.appsmith.server.domains.UserState; @@ -103,7 +103,7 @@ public class UserServiceTest { EmailVerificationTokenRepository emailVerificationTokenRepository; @Autowired - TenantService tenantService; + OrganizationService organizationService; Mono userMono; @@ -187,7 +187,7 @@ public void createNewUserValid() { assertThat(user.getId()).isNotNull(); assertThat(user.getEmail()).isEqualTo("new-user-email@email.com"); assertThat(user.getName()).isNullOrEmpty(); - assertThat(user.getTenantId()).isNotNull(); + assertThat(user.getOrganizationId()).isNotNull(); Set userPolicies = user.getPolicies(); Optional optionalManageUserPolicy = userPolicies.stream() @@ -667,21 +667,23 @@ public void emailVerificationTokenGenerate_WhenInstanceEmailVerificationIsNotEna newUser.setEmail(testEmail); Mono userMono = userRepository.save(newUser); - // Setting tenant Config emailVerificationEnabled to FALSE - Mono tenantMono = tenantService.getDefaultTenant().flatMap(tenant1 -> { - TenantConfiguration tenantConfiguration = tenant1.getTenantConfiguration(); - tenantConfiguration.setEmailVerificationEnabled(Boolean.FALSE); - tenant1.setTenantConfiguration(tenantConfiguration); - return tenantService.update(tenant1.getId(), tenant1); - }); + // Setting Organization Config emailVerificationEnabled to FALSE + Mono organizationMono = organizationService + .getDefaultOrganization() + .flatMap(organization -> { + OrganizationConfiguration organizationConfiguration = organization.getOrganizationConfiguration(); + organizationConfiguration.setEmailVerificationEnabled(Boolean.FALSE); + organization.setOrganizationConfiguration(organizationConfiguration); + return organizationService.update(organization.getId(), organization); + }); Mono emailVerificationMono = userService.resendEmailVerification(getResendEmailVerificationDTO(testEmail), null); - Mono resultMono = userMono.then(tenantMono).then(emailVerificationMono); + Mono resultMono = userMono.then(organizationMono).then(emailVerificationMono); StepVerifier.create(resultMono) - .expectErrorMessage(AppsmithError.TENANT_EMAIL_VERIFICATION_NOT_ENABLED.getMessage()) + .expectErrorMessage(AppsmithError.ORGANIZATION_EMAIL_VERIFICATION_NOT_ENABLED.getMessage()) .verify(); } @@ -695,18 +697,20 @@ public void emailVerificationTokenGenerate_WhenUserEmailAlreadyVerified_ThrowsEx newUser.setEmailVerified(Boolean.TRUE); Mono userMono = userRepository.save(newUser); - // Setting tenant Config emailVerificationEnabled to TRUE - Mono tenantMono = tenantService.getDefaultTenant().flatMap(tenant1 -> { - TenantConfiguration tenantConfiguration = tenant1.getTenantConfiguration(); - tenantConfiguration.setEmailVerificationEnabled(Boolean.TRUE); - tenant1.setTenantConfiguration(tenantConfiguration); - return tenantService.update(tenant1.getId(), tenant1); - }); + // Setting Organization Config emailVerificationEnabled to TRUE + Mono organizationMono = organizationService + .getDefaultOrganization() + .flatMap(organization -> { + OrganizationConfiguration organizationConfiguration = organization.getOrganizationConfiguration(); + organizationConfiguration.setEmailVerificationEnabled(Boolean.TRUE); + organization.setOrganizationConfiguration(organizationConfiguration); + return organizationService.update(organization.getId(), organization); + }); Mono emailVerificationMono = userService.resendEmailVerification(getResendEmailVerificationDTO(testEmail), null); - Mono resultMono = userMono.then(tenantMono).then(emailVerificationMono); + Mono resultMono = userMono.then(organizationMono).then(emailVerificationMono); StepVerifier.create(resultMono) .expectErrorMessage(AppsmithError.USER_ALREADY_VERIFIED.getMessage()) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java index 22b53e0cce3b..f7ca9468321a 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java @@ -252,7 +252,7 @@ public void getUserWorkspacesByRecentlyUsedOrder_noRecentWorkspaces_allEntriesAr assertThat(workspaces).hasSize(4); workspaces.forEach(workspace -> { assertThat(workspaceIds.contains(workspace.getId())).isTrue(); - assertThat(workspace.getTenantId()).isNotEmpty(); + assertThat(workspace.getOrganizationId()).isNotEmpty(); }); }) .verifyComplete(); @@ -281,7 +281,7 @@ public void getUserWorkspacesByRecentlyUsedOrder_withRecentlyUsedWorkspaces_allE workspaces.forEach(workspace -> { fetchedWorkspaceIds.add(workspace.getId()); assertThat(workspaceIds.contains(workspace.getId())).isTrue(); - assertThat(workspace.getTenantId()).isNotEmpty(); + assertThat(workspace.getOrganizationId()).isNotEmpty(); }); assertThat(fetchedWorkspaceIds).isEqualTo(workspaceIds); }) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/WorkspaceServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/WorkspaceServiceTest.java index 3af09f039fcf..8ae96af4c516 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/WorkspaceServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/WorkspaceServiceTest.java @@ -180,7 +180,7 @@ public void createDefaultWorkspace() { assertThat(workspace1.getSlug()).isNotNull(); assertThat(workspace1.getEmail()).isEqualTo("api_user"); assertThat(workspace1.getIsAutoGeneratedWorkspace()).isTrue(); - assertThat(workspace1.getTenantId()).isEqualTo(user.getTenantId()); + assertThat(workspace1.getOrganizationId()).isEqualTo(user.getOrganizationId()); assertThat(workspace1.getDefaultPermissionGroups()).hasSize(3); PermissionGroup adminPermissionGroup = permissionGroups.stream() @@ -338,7 +338,7 @@ public void validCreateWorkspaceTest() { assertThat(workspace1.getSlug()).isEqualTo(TextUtils.makeSlug(workspace.getName())); assertThat(workspace1.getEmail()).isEqualTo("api_user"); assertThat(workspace1.getIsAutoGeneratedWorkspace()).isNull(); - assertThat(workspace1.getTenantId()).isEqualTo(user.getTenantId()); + assertThat(workspace1.getOrganizationId()).isEqualTo(user.getOrganizationId()); // Assert admin permission group policies adminPermissionGroup.getPolicies().stream() diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java index bdeea2812344..16f6198daa64 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ConsolidatedAPIServiceImplTest.java @@ -13,8 +13,8 @@ import com.appsmith.server.domains.CustomJSLib; import com.appsmith.server.domains.GitArtifactMetadata; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.Plugin; -import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.Theme; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; @@ -42,9 +42,9 @@ import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.ConsolidatedAPIService; import com.appsmith.server.services.MockDataService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.ProductAlertService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import com.appsmith.server.themes.base.ThemeService; @@ -96,7 +96,7 @@ public class ConsolidatedAPIServiceImplTest { UserDataService mockUserDataService; @MockBean - TenantService mockTenantService; + OrganizationService mockOrganizationService; @MockBean ProductAlertService mockProductAlertService; @@ -163,9 +163,9 @@ public void testPageLoadResponseWhenPageIdAndApplicationIdMissing() { sampleFeatureFlagMap.put("sampleFeatureFlag", true); when(mockUserDataService.getFeatureFlagsForCurrentUser()).thenReturn(Mono.just(sampleFeatureFlagMap)); - Tenant sampleTenant = new Tenant(); - sampleTenant.setDisplayName("sampleTenant"); - when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + Organization sampleOrganization = new Organization(); + sampleOrganization.setDisplayName("sampleOrganization"); + when(mockOrganizationService.getOrganizationConfiguration()).thenReturn(Mono.just(sampleOrganization)); ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); @@ -185,11 +185,11 @@ public void testPageLoadResponseWhenPageIdAndApplicationIdMissing() { .getData() .getName()); - assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertNotNull(consolidatedAPIResponseDTO.getOrganizationConfig()); assertEquals( - "sampleTenant", + "sampleOrganization", consolidatedAPIResponseDTO - .getTenantConfig() + .getOrganizationConfig() .getData() .getDisplayName()); @@ -223,9 +223,9 @@ public void testPageLoadResponseForViewMode() { sampleFeatureFlagMap.put("sampleFeatureFlag", true); when(mockUserDataService.getFeatureFlagsForCurrentUser()).thenReturn(Mono.just(sampleFeatureFlagMap)); - Tenant sampleTenant = new Tenant(); - sampleTenant.setDisplayName("sampleTenant"); - when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + Organization sampleOrganization = new Organization(); + sampleOrganization.setDisplayName("sampleOrganization"); + when(mockOrganizationService.getOrganizationConfiguration()).thenReturn(Mono.just(sampleOrganization)); ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); @@ -312,11 +312,11 @@ public void testPageLoadResponseForViewMode() { .getData() .getName()); - assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertNotNull(consolidatedAPIResponseDTO.getOrganizationConfig()); assertEquals( - "sampleTenant", + "sampleOrganization", consolidatedAPIResponseDTO - .getTenantConfig() + .getOrganizationConfig() .getData() .getDisplayName()); @@ -412,9 +412,9 @@ public void testPageLoadResponseForEditMode() { sampleFeatureFlagMap.put("sampleFeatureFlag", true); when(mockUserDataService.getFeatureFlagsForCurrentUser()).thenReturn(Mono.just(sampleFeatureFlagMap)); - Tenant sampleTenant = new Tenant(); - sampleTenant.setDisplayName("sampleTenant"); - when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + Organization sampleOrganization = new Organization(); + sampleOrganization.setDisplayName("sampleOrganization"); + when(mockOrganizationService.getOrganizationConfiguration()).thenReturn(Mono.just(sampleOrganization)); ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); @@ -538,11 +538,11 @@ public void testPageLoadResponseForEditMode() { .getData() .getName()); - assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertNotNull(consolidatedAPIResponseDTO.getOrganizationConfig()); assertEquals( - "sampleTenant", + "sampleOrganization", consolidatedAPIResponseDTO - .getTenantConfig() + .getOrganizationConfig() .getData() .getDisplayName()); @@ -731,9 +731,9 @@ public void testErrorResponseWhenAnonymousUserAccessPrivateApp() { sampleFeatureFlagMap.put("sampleFeatureFlag", true); when(mockUserDataService.getFeatureFlagsForCurrentUser()).thenReturn(Mono.just(sampleFeatureFlagMap)); - Tenant sampleTenant = new Tenant(); - sampleTenant.setDisplayName("sampleTenant"); - when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + Organization sampleOrganization = new Organization(); + sampleOrganization.setDisplayName("sampleOrganization"); + when(mockOrganizationService.getOrganizationConfiguration()).thenReturn(Mono.just(sampleOrganization)); ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); @@ -760,11 +760,11 @@ public void testErrorResponseWhenAnonymousUserAccessPrivateApp() { .getData() .getName()); - assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertNotNull(consolidatedAPIResponseDTO.getOrganizationConfig()); assertEquals( - "sampleTenant", + "sampleOrganization", consolidatedAPIResponseDTO - .getTenantConfig() + .getOrganizationConfig() .getData() .getDisplayName()); @@ -903,9 +903,9 @@ public void testPageLoadResponseForViewMode_whenBranchNameIsPresentInNonGitApp() sampleFeatureFlagMap.put("sampleFeatureFlag", true); when(mockUserDataService.getFeatureFlagsForCurrentUser()).thenReturn(Mono.just(sampleFeatureFlagMap)); - Tenant sampleTenant = new Tenant(); - sampleTenant.setDisplayName("sampleTenant"); - when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + Organization sampleOrganization = new Organization(); + sampleOrganization.setDisplayName("sampleOrganization"); + when(mockOrganizationService.getOrganizationConfiguration()).thenReturn(Mono.just(sampleOrganization)); ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); @@ -992,11 +992,11 @@ public void testPageLoadResponseForViewMode_whenBranchNameIsPresentInNonGitApp() .getData() .getName()); - assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertNotNull(consolidatedAPIResponseDTO.getOrganizationConfig()); assertEquals( - "sampleTenant", + "sampleOrganization", consolidatedAPIResponseDTO - .getTenantConfig() + .getOrganizationConfig() .getData() .getDisplayName()); @@ -1095,9 +1095,9 @@ public void testPageLoadResponseForEditModeWhenDefaultBranchIsDifferentFromDefau when(mockUserDataService.updateLastUsedResourceAndWorkspaceList(any(), any(), any())) .thenReturn(Mono.just(new UserData())); - Tenant sampleTenant = new Tenant(); - sampleTenant.setDisplayName("sampleTenant"); - when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + Organization sampleOrganization = new Organization(); + sampleOrganization.setDisplayName("sampleOrganization"); + when(mockOrganizationService.getOrganizationConfiguration()).thenReturn(Mono.just(sampleOrganization)); ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); @@ -1250,11 +1250,11 @@ public void testPageLoadResponseForEditModeWhenDefaultBranchIsDifferentFromDefau .getData() .getName()); - assertNotNull(consolidatedAPIResponseDTO.getTenantConfig()); + assertNotNull(consolidatedAPIResponseDTO.getOrganizationConfig()); assertEquals( - "sampleTenant", + "sampleOrganization", consolidatedAPIResponseDTO - .getTenantConfig() + .getOrganizationConfig() .getData() .getDisplayName()); @@ -1441,9 +1441,9 @@ public void testPageLoadWhenPageFromFeatureBranchAndCacheableRepositoryReturnsBa when(mockUserDataService.updateLastUsedResourceAndWorkspaceList(any(), any(), any())) .thenReturn(Mono.just(new UserData())); - Tenant sampleTenant = new Tenant(); - sampleTenant.setDisplayName("sampleTenant"); - when(mockTenantService.getTenantConfiguration()).thenReturn(Mono.just(sampleTenant)); + Organization sampleOrganization = new Organization(); + sampleOrganization.setDisplayName("sampleOrganization"); + when(mockOrganizationService.getOrganizationConfiguration()).thenReturn(Mono.just(sampleOrganization)); ProductAlertResponseDTO sampleProductAlertResponseDTO = new ProductAlertResponseDTO(); sampleProductAlertResponseDTO.setTitle("sampleProductAlert"); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java index 4ad36c2a26fe..84900e41745f 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java @@ -5,7 +5,6 @@ import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.notifications.EmailSender; -import com.appsmith.server.services.TenantService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -39,9 +38,6 @@ @SpringBootTest class EmailServiceCEImplTest { - @Autowired - TenantService tenantService; - @SpyBean EmailSender mockEmailSender; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java index e4b875e2672f..89129e40c09d 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java @@ -9,7 +9,7 @@ import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.services.CacheableFeatureFlagHelper; import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -31,7 +31,7 @@ import java.util.Map; import java.util.UUID; -import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; +import static com.appsmith.external.enums.FeatureFlagEnum.ORGANIZATION_TEST_FEATURE; import static com.appsmith.server.constants.FeatureMigrationType.DISABLE; import static com.appsmith.server.constants.FeatureMigrationType.ENABLE; import static com.appsmith.server.constants.MigrationStatus.COMPLETED; @@ -65,7 +65,7 @@ public class FeatureFlagServiceCETest { FeatureFlagMigrationHelper featureFlagMigrationHelper; @Autowired - TenantService tenantService; + OrganizationService organizationService; @BeforeEach void setup() { @@ -78,7 +78,7 @@ void setup() { @AfterEach void tearDown() { cacheManager.evictAll("featureFlag").block(); - cacheManager.evictAll("tenantNewFeatures").block(); + cacheManager.evictAll("organizationNewFeatures").block(); } @Test @@ -102,26 +102,26 @@ public void testGetFeaturesForUser() { @Test @WithUserDetails(value = "api_user") - public void testGetFeaturesForUser_overrideWithTenantFeature() { + public void testGetFeaturesForUser_overrideWithOrganizationFeature() { - // Assert feature flag is false before the tenant level flag overrides the existing flag + // Assert feature flag is false before the org level flag overrides the existing flag StepVerifier.create(featureFlagService.getAllFeatureFlagsForUser()) .assertNext(result -> { assertNotNull(result); - assertTrue(result.get(TENANT_TEST_FEATURE.toString())); + assertTrue(result.get(ORGANIZATION_TEST_FEATURE.toString())); }) .verifyComplete(); - Map tenantFeatures = new HashMap<>(); - tenantFeatures.put(TENANT_TEST_FEATURE.toString(), false); + Map organizationFeatures = new HashMap<>(); + organizationFeatures.put(ORGANIZATION_TEST_FEATURE.toString(), false); FeaturesResponseDTO responseDTO = new FeaturesResponseDTO(); - responseDTO.setFeatures(tenantFeatures); - doReturn(Mono.just(responseDTO)).when(cacheableFeatureFlagHelper).getRemoteFeaturesForTenant(any()); - // Assert true for same feature flag after tenant level flag overrides the existing flag + responseDTO.setFeatures(organizationFeatures); + doReturn(Mono.just(responseDTO)).when(cacheableFeatureFlagHelper).getRemoteFeaturesForOrganization(any()); + // Assert true for same feature flag after org level flag overrides the existing flag StepVerifier.create(featureFlagService.getAllFeatureFlagsForUser()) .assertNext(result -> { assertNotNull(result); - assertFalse(result.get(TENANT_TEST_FEATURE.toString())); + assertFalse(result.get(ORGANIZATION_TEST_FEATURE.toString())); }) .verifyComplete(); } @@ -148,7 +148,7 @@ public void evictFeatureFlags_withUserIdentifier_redisKeyDoesNotExist() { } @Test - public void getFeatures_withTenantIdentifier_redisKeyExists() { + public void getFeatures_withOrganizationIdentifier_redisKeyExists() { Map flags = new HashMap<>(); flags.put(UUID.randomUUID().toString(), true); flags.put(UUID.randomUUID().toString(), false); @@ -157,20 +157,20 @@ public void getFeatures_withTenantIdentifier_redisKeyExists() { doReturn(Mono.just(featuresResponseDTO)) .when(cacheableFeatureFlagHelper) - .getRemoteFeaturesForTenant(any()); + .getRemoteFeaturesForOrganization(any()); - String tenantIdentifier = UUID.randomUUID().toString(); + String organizationIdentifier = UUID.randomUUID().toString(); Mono cachedFeaturesMono = - cacheableFeatureFlagHelper.fetchCachedTenantFeatures(tenantIdentifier); - Mono hasKeyMono = reactiveRedisTemplate.hasKey("tenantNewFeatures:" + tenantIdentifier); + cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(organizationIdentifier); + Mono hasKeyMono = reactiveRedisTemplate.hasKey("organizationNewFeatures:" + organizationIdentifier); StepVerifier.create(cachedFeaturesMono.then(hasKeyMono)) .assertNext(Assertions::assertTrue) .verifyComplete(); } @Test - public void evictFeatures_withTenantIdentifier_redisKeyDoesNotExist() { - // Insert dummy value for tenant flags + public void evictFeatures_withOrganizationIdentifier_redisKeyDoesNotExist() { + // Insert dummy value for org flags Map flags = new HashMap<>(); flags.put(UUID.randomUUID().toString(), true); flags.put(UUID.randomUUID().toString(), false); @@ -179,19 +179,19 @@ public void evictFeatures_withTenantIdentifier_redisKeyDoesNotExist() { doReturn(Mono.just(featuresResponseDTO)) .when(cacheableFeatureFlagHelper) - .getRemoteFeaturesForTenant(any()); + .getRemoteFeaturesForOrganization(any()); - String tenantIdentifier = UUID.randomUUID().toString(); + String organizationIdentifier = UUID.randomUUID().toString(); Mono cachedFeaturesMono = - cacheableFeatureFlagHelper.fetchCachedTenantFeatures(tenantIdentifier); - Mono hasKeyMono = reactiveRedisTemplate.hasKey("tenantNewFeatures:" + tenantIdentifier); + cacheableFeatureFlagHelper.fetchCachedOrganizationFeatures(organizationIdentifier); + Mono hasKeyMono = reactiveRedisTemplate.hasKey("organizationNewFeatures:" + organizationIdentifier); // Assert key is inserted in cache StepVerifier.create(cachedFeaturesMono.then(hasKeyMono)) .assertNext(Assertions::assertTrue) .verifyComplete(); - Mono evictCache = cacheableFeatureFlagHelper.evictCachedTenantFeatures(tenantIdentifier); - hasKeyMono = reactiveRedisTemplate.hasKey("tenantNewFeatures:" + tenantIdentifier); + Mono evictCache = cacheableFeatureFlagHelper.evictCachedOrganizationFeatures(organizationIdentifier); + hasKeyMono = reactiveRedisTemplate.hasKey("organizationNewFeatures:" + organizationIdentifier); // Assert key is evicted from cache StepVerifier.create(evictCache.then(hasKeyMono)) .assertNext(Assertions::assertFalse) @@ -200,19 +200,19 @@ public void evictFeatures_withTenantIdentifier_redisKeyDoesNotExist() { @Test public void - getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations_emptyMapForPendingMigration_statesUpdate() { + getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations_emptyMapForPendingMigration_statesUpdate() { Mockito.when(featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(any())) .thenReturn(Mono.just(new HashMap<>())); featureFlagService - .getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations() + .getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations() .block(); - StepVerifier.create(tenantService.getDefaultTenant()) - .assertNext(tenant -> { - assertThat(tenant.getTenantConfiguration().getFeaturesWithPendingMigration()) + StepVerifier.create(organizationService.getDefaultOrganization()) + .assertNext(organization -> { + assertThat(organization.getOrganizationConfiguration().getFeaturesWithPendingMigration()) .isEqualTo(new HashMap<>()); - assertThat(tenant.getTenantConfiguration().getMigrationStatus()) + assertThat(organization.getOrganizationConfiguration().getMigrationStatus()) .isEqualTo(COMPLETED); }) .verifyComplete(); @@ -220,80 +220,82 @@ public void evictFeatures_withTenantIdentifier_redisKeyDoesNotExist() { @Test public void - getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations_disableMigration_statesUpdate() { + getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations_disableMigration_statesUpdate() { Mockito.when(featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(any())) - .thenReturn(Mono.just(Map.of(TENANT_TEST_FEATURE, DISABLE))); + .thenReturn(Mono.just(Map.of(ORGANIZATION_TEST_FEATURE, DISABLE))); featureFlagService - .getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations() + .getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations() .block(); - StepVerifier.create(tenantService.getDefaultTenant()) - .assertNext(tenant -> { - assertThat(tenant.getTenantConfiguration().getFeaturesWithPendingMigration()) - .isEqualTo(Map.of(TENANT_TEST_FEATURE, DISABLE)); - assertThat(tenant.getTenantConfiguration().getMigrationStatus()) + StepVerifier.create(organizationService.getDefaultOrganization()) + .assertNext(organization -> { + assertThat(organization.getOrganizationConfiguration().getFeaturesWithPendingMigration()) + .isEqualTo(Map.of(ORGANIZATION_TEST_FEATURE, DISABLE)); + assertThat(organization.getOrganizationConfiguration().getMigrationStatus()) .isEqualTo(PENDING); }) .verifyComplete(); } @Test - public void getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations_enableMigration_statesUpdate() { + public void + getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations_enableMigration_statesUpdate() { Mockito.when(featureFlagMigrationHelper.getUpdatedFlagsWithPendingMigration(any())) - .thenReturn(Mono.just(Map.of(TENANT_TEST_FEATURE, ENABLE))); + .thenReturn(Mono.just(Map.of(ORGANIZATION_TEST_FEATURE, ENABLE))); featureFlagService - .getAllRemoteFeaturesForTenantAndUpdateFeatureFlagsWithPendingMigrations() + .getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithPendingMigrations() .block(); - StepVerifier.create(tenantService.getDefaultTenant()) - .assertNext(tenant -> { - assertThat(tenant.getTenantConfiguration().getFeaturesWithPendingMigration()) - .isEqualTo(Map.of(TENANT_TEST_FEATURE, ENABLE)); - assertThat(tenant.getTenantConfiguration().getMigrationStatus()) + StepVerifier.create(organizationService.getDefaultOrganization()) + .assertNext(organization -> { + assertThat(organization.getOrganizationConfiguration().getFeaturesWithPendingMigration()) + .isEqualTo(Map.of(ORGANIZATION_TEST_FEATURE, ENABLE)); + assertThat(organization.getOrganizationConfiguration().getMigrationStatus()) .isEqualTo(PENDING); }) .verifyComplete(); } @Test - public void getTenantFeatureFlags_withDefaultTenant_fetchLatestFlags() { + public void getOrganizationFeatureFlags_withDefaultOrganization_fetchLatestFlags() { - Map tenantFeatures = new HashMap<>(); - tenantFeatures.put(TENANT_TEST_FEATURE.name(), true); + Map organizationFeatures = new HashMap<>(); + organizationFeatures.put(ORGANIZATION_TEST_FEATURE.name(), true); FeaturesResponseDTO responseDTO = new FeaturesResponseDTO(); - responseDTO.setFeatures(tenantFeatures); - doReturn(Mono.just(responseDTO)).when(cacheableFeatureFlagHelper).getRemoteFeaturesForTenant(any()); - StepVerifier.create(featureFlagService.getTenantFeatures()) + responseDTO.setFeatures(organizationFeatures); + doReturn(Mono.just(responseDTO)).when(cacheableFeatureFlagHelper).getRemoteFeaturesForOrganization(any()); + StepVerifier.create(featureFlagService.getOrganizationFeatures()) .assertNext(result -> { assertNotNull(result); - assertTrue(result.get(TENANT_TEST_FEATURE.name())); + assertTrue(result.get(ORGANIZATION_TEST_FEATURE.name())); }) .verifyComplete(); } @Test - public void getCachedTenantFeatureFlags_withDefaultTenant_tenantFeatureFlagsAreCached() { + public void getCachedOrganizationFeatureFlags_withDefaultOrganization_organizationFeatureFlagsAreCached() { // Assert that the cached feature flags are empty before the remote fetch - CachedFeatures cachedFeaturesBeforeRemoteCall = featureFlagService.getCachedTenantFeatureFlags(); + CachedFeatures cachedFeaturesBeforeRemoteCall = featureFlagService.getCachedOrganizationFeatureFlags(); assertThat(cachedFeaturesBeforeRemoteCall.getFeatures()).hasSize(1); - assertTrue(cachedFeaturesBeforeRemoteCall.getFeatures().get(TENANT_TEST_FEATURE.name())); + assertTrue(cachedFeaturesBeforeRemoteCall.getFeatures().get(ORGANIZATION_TEST_FEATURE.name())); - Map tenantFeatures = new HashMap<>(); - tenantFeatures.put(TENANT_TEST_FEATURE.name(), false); + Map organizationFeatures = new HashMap<>(); + organizationFeatures.put(ORGANIZATION_TEST_FEATURE.name(), false); FeaturesResponseDTO responseDTO = new FeaturesResponseDTO(); - responseDTO.setFeatures(tenantFeatures); - doReturn(Mono.just(responseDTO)).when(cacheableFeatureFlagHelper).getRemoteFeaturesForTenant(any()); - StepVerifier.create(featureFlagService.getTenantFeatures()) + responseDTO.setFeatures(organizationFeatures); + doReturn(Mono.just(responseDTO)).when(cacheableFeatureFlagHelper).getRemoteFeaturesForOrganization(any()); + StepVerifier.create(featureFlagService.getOrganizationFeatures()) .assertNext(result -> { assertNotNull(result); - assertFalse(result.get(TENANT_TEST_FEATURE.name())); + assertFalse(result.get(ORGANIZATION_TEST_FEATURE.name())); // Check if the cached feature flags are updated after the remote fetch - CachedFeatures cachedFeaturesAfterRemoteCall = featureFlagService.getCachedTenantFeatureFlags(); - assertFalse(cachedFeaturesAfterRemoteCall.getFeatures().get(TENANT_TEST_FEATURE.name())); + CachedFeatures cachedFeaturesAfterRemoteCall = + featureFlagService.getCachedOrganizationFeatureFlags(); + assertFalse(cachedFeaturesAfterRemoteCall.getFeatures().get(ORGANIZATION_TEST_FEATURE.name())); }) .verifyComplete(); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/OrganizationServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/OrganizationServiceCETest.java new file mode 100644 index 000000000000..a9b1dd8c8211 --- /dev/null +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/OrganizationServiceCETest.java @@ -0,0 +1,414 @@ +package com.appsmith.server.services.ce; + +import com.appsmith.caching.components.CacheManager; +import com.appsmith.external.enums.FeatureFlagEnum; +import com.appsmith.server.constants.FeatureMigrationType; +import com.appsmith.server.constants.LicensePlan; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; +import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.FeatureFlagMigrationHelper; +import com.appsmith.server.helpers.UserUtils; +import com.appsmith.server.helpers.ce.bridge.Bridge; +import com.appsmith.server.repositories.CacheableRepositoryHelper; +import com.appsmith.server.repositories.OrganizationRepository; +import com.appsmith.server.repositories.UserRepository; +import com.appsmith.server.services.FeatureFlagService; +import com.appsmith.server.services.OrganizationService; +import com.appsmith.server.solutions.EnvManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.data.redis.core.ReactiveRedisTemplate; +import org.springframework.security.test.context.support.WithUserDetails; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static com.appsmith.external.enums.FeatureFlagEnum.ORGANIZATION_TEST_FEATURE; +import static com.appsmith.external.enums.FeatureFlagEnum.TEST_FEATURE_2; +import static com.appsmith.server.constants.MigrationStatus.COMPLETED; +import static com.appsmith.server.constants.MigrationStatus.IN_PROGRESS; +import static com.appsmith.server.exceptions.AppsmithErrorCode.FEATURE_FLAG_MIGRATION_FAILURE; +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; + +@SpringBootTest +class OrganizationServiceCETest { + + @Autowired + OrganizationService organizationService; + + @MockBean + EnvManager envManager; + + @Autowired + UserRepository userRepository; + + @Autowired + OrganizationRepository organizationRepository; + + @Autowired + UserUtils userUtils; + + @SpyBean + FeatureFlagService featureFlagService; + + @Autowired + ReactiveRedisTemplate reactiveRedisTemplate; + + @SpyBean + CacheManager cacheManager; + + @SpyBean + CacheableRepositoryHelper cacheableRepositoryHelper; + + @MockBean + FeatureFlagMigrationHelper featureFlagMigrationHelper; + + OrganizationConfiguration originalOrganizationConfiguration; + + @BeforeEach + public void setup() throws IOException { + final Organization organization = + organizationService.getDefaultOrganization().block(); + assert organization != null; + originalOrganizationConfiguration = organization.getOrganizationConfiguration(); + + organizationRepository + .updateAndReturn( + organization.getId(), + Bridge.update().set(Organization.Fields.organizationConfiguration, null), + null) + .block(); + + // Make api_user super-user to test organization admin functionality + // Todo change this to organization admin once we introduce multitenancy + userRepository + .findByEmail("api_user") + .flatMap(user -> userUtils.makeSuperUser(List.of(user))) + .block(); + doReturn(Mono.empty()).when(cacheManager).get(anyString(), anyString()); + } + + @AfterEach + public void cleanup() { + Organization updatedOrganization = new Organization(); + updatedOrganization.setOrganizationConfiguration(originalOrganizationConfiguration); + organizationService + .getDefaultOrganizationId() + .flatMap(organizationId -> organizationService.update(organizationId, updatedOrganization)) + .doOnError(error -> { + System.err.println("Error during cleanup: " + error.getMessage()); + }) + .block(); + } + + @Test + void ensureMapsKey() { + StepVerifier.create(organizationService.getOrganizationConfiguration()) + .assertNext(organization -> { + assertThat(organization.getOrganizationConfiguration().getGoogleMapsKey()) + .isNull(); + }) + .verifyComplete(); + } + + @Test + @WithUserDetails("api_user") + void setMapsKeyAndGetItBack() { + final OrganizationConfiguration changes = new OrganizationConfiguration(); + changes.setGoogleMapsKey("test-key"); + + final Mono resultMono = organizationService + .updateDefaultOrganizationConfiguration(changes) + .map(Organization::getOrganizationConfiguration); + + StepVerifier.create(resultMono) + .assertNext(organizationConfiguration -> { + assertThat(organizationConfiguration.getGoogleMapsKey()).isEqualTo("test-key"); + }) + .verifyComplete(); + } + + @Test + void setMapsKeyWithoutAuthentication() { + final OrganizationConfiguration changes = new OrganizationConfiguration(); + changes.setGoogleMapsKey("test-key"); + + final Mono resultMono = organizationService.updateDefaultOrganizationConfiguration(changes); + + StepVerifier.create(resultMono) + .expectErrorMatches(error -> { + assertThat(error.getMessage()).startsWith("Unable to find organization "); + return true; + }) + .verify(); + } + + @Test + @WithUserDetails("usertest@usertest.com") + void setMapsKeyWithoutAuthorization() { + final OrganizationConfiguration changes = new OrganizationConfiguration(); + changes.setGoogleMapsKey("test-key"); + + final Mono resultMono = organizationService.updateDefaultOrganizationConfiguration(changes); + + StepVerifier.create(resultMono) + .expectErrorMatches(error -> { + assertThat(error.getMessage()).startsWith("Unable to find organization "); + return true; + }) + .verify(); + } + + @Test + @WithUserDetails("anonymousUser") + void getOrganizationConfig_Valid_AnonymousUser() { + StepVerifier.create(organizationService.getOrganizationConfiguration()) + .assertNext(organization -> { + assertThat(organization.getOrganizationConfiguration()).isNotNull(); + assertThat(organization.getOrganizationConfiguration().getLicense()) + .isNotNull(); + assertThat(organization + .getOrganizationConfiguration() + .getLicense() + .getPlan()) + .isEqualTo(LicensePlan.FREE); + }) + .verifyComplete(); + } + + @Test + @WithUserDetails("api_user") + void setEmailVerificationEnabled_WithInvalidSMTPHost_ReturnsError() { + final OrganizationConfiguration changes = new OrganizationConfiguration(); + changes.setEmailVerificationEnabled(TRUE); + + Map envVars = new HashMap<>(); + // adding invalid mail host + envVars.put("APPSMITH_MAIL_HOST", ""); + + // mocking env vars file + Mockito.when(envManager.getAllNonEmpty()).thenReturn(Mono.just(envVars)); + + final Mono resultMono = organizationService + .updateDefaultOrganizationConfiguration(changes) + .then(organizationService.getOrganizationConfiguration()) + .map(Organization::getOrganizationConfiguration); + + StepVerifier.create(resultMono) + .expectErrorMatches(error -> { + assertThat(error.getMessage()).startsWith("Your SMTP configuration is invalid"); + return true; + }) + .verify(); + } + + @Test + @WithUserDetails("api_user") + void setEmailVerificationEnabled_WithValidSMTPHost_Success() { + final OrganizationConfiguration changes = new OrganizationConfiguration(); + changes.setEmailVerificationEnabled(TRUE); + + Map envVars = new HashMap<>(); + // adding valid mail host + envVars.put("APPSMITH_MAIL_HOST", "smtp.sendgrid.net"); + + // mocking env vars file + Mockito.when(envManager.getAllNonEmpty()).thenReturn(Mono.just(envVars)); + + final Mono resultMono = organizationService + .updateDefaultOrganizationConfiguration(changes) + .then(organizationService.getOrganizationConfiguration()) + .map(Organization::getOrganizationConfiguration); + + StepVerifier.create(resultMono) + .assertNext(organizationConfiguration -> { + assertThat(organizationConfiguration.isEmailVerificationEnabled()) + .isTrue(); + }) + .verifyComplete(); + } + + @Test + @WithUserDetails("api_user") + void setEmailVerificationEnabledFalseAndGetItBack() { + final OrganizationConfiguration changes = new OrganizationConfiguration(); + changes.setEmailVerificationEnabled(Boolean.FALSE); + + final Mono resultMono = organizationService + .updateDefaultOrganizationConfiguration(changes) + .then(organizationService.getOrganizationConfiguration()) + .map(Organization::getOrganizationConfiguration); + + StepVerifier.create(resultMono) + .assertNext(organizationConfiguration -> { + assertThat(organizationConfiguration.isEmailVerificationEnabled()) + .isFalse(); + }) + .verifyComplete(); + } + + @Test + void checkAndExecuteMigrationsForOrganizationFeatureFlags_emptyMigrationMap_revertSameOrganization() { + Mockito.when(featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(any(), any())) + .thenReturn(Mono.just(TRUE)); + + Organization organization = new Organization(); + organization.setId(UUID.randomUUID().toString()); + OrganizationConfiguration config = new OrganizationConfiguration(); + config.setFeaturesWithPendingMigration(new HashMap<>()); + organization.setOrganizationConfiguration(config); + final Mono resultMono = + organizationService.checkAndExecuteMigrationsForOrganizationFeatureFlags(organization); + StepVerifier.create(resultMono) + .assertNext(organization1 -> { + assertThat(organization1).isEqualTo(organization); + assertThat(organization1.getOrganizationConfiguration().getFeaturesWithPendingMigration()) + .isEmpty(); + assertThat(organization1.getOrganizationConfiguration().getMigrationStatus()) + .isEqualTo(COMPLETED); + }) + .verifyComplete(); + } + + @Test + void checkAndExecuteMigrationsForOrganizationFeatureFlags_withPendingMigration_getUpdatedOrganization() { + Mockito.when(featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(any(), any())) + .thenReturn(Mono.just(TRUE)); + + Organization organization = new Organization(); + organization.setId(UUID.randomUUID().toString()); + OrganizationConfiguration config = new OrganizationConfiguration(); + Map featureMigrationTypeMap = new HashMap<>(); + config.setFeaturesWithPendingMigration(featureMigrationTypeMap); + featureMigrationTypeMap.put(ORGANIZATION_TEST_FEATURE, FeatureMigrationType.ENABLE); + featureMigrationTypeMap.put(TEST_FEATURE_2, FeatureMigrationType.DISABLE); + organization.setOrganizationConfiguration(config); + final Mono resultMono = + organizationService.checkAndExecuteMigrationsForOrganizationFeatureFlags(organization); + StepVerifier.create(resultMono) + .assertNext(organization1 -> { + assertThat(organization1.getOrganizationConfiguration().getFeaturesWithPendingMigration()) + .isEmpty(); + assertThat(organization1.getOrganizationConfiguration().getMigrationStatus()) + .isEqualTo(COMPLETED); + }) + .verifyComplete(); + } + + @Test + @WithUserDetails("api_user") + void + checkAndExecuteMigrationsForOrganizationFeatureFlags_withPendingMigration_exceptionWhileRunningMigration_getUpdatedOrganization() { + Mockito.when(featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(any(), any())) + .thenReturn(Mono.just(TRUE)) + .thenReturn(Mono.just(FALSE)); + + Organization organization = new Organization(); + organization.setId(UUID.randomUUID().toString()); + OrganizationConfiguration config = new OrganizationConfiguration(); + Map featureMigrationTypeMap = new HashMap<>(); + config.setFeaturesWithPendingMigration(featureMigrationTypeMap); + featureMigrationTypeMap.put(ORGANIZATION_TEST_FEATURE, FeatureMigrationType.DISABLE); + featureMigrationTypeMap.put(TEST_FEATURE_2, FeatureMigrationType.ENABLE); + organization.setOrganizationConfiguration(config); + final Mono resultMono = + organizationService.checkAndExecuteMigrationsForOrganizationFeatureFlags(organization); + + // Verify that the feature flag migration failure is thrown + StepVerifier.create(resultMono) + .expectErrorSatisfies(throwable -> { + assertThat(throwable instanceof AppsmithException).isTrue(); + assertThat(((AppsmithException) throwable).getAppErrorCode()) + .isEqualTo(FEATURE_FLAG_MIGRATION_FAILURE.getCode()); + }) + .verify(); + + // Verify that the organization is updated for the feature flag migration failure + StepVerifier.create(organizationService.getByIdWithoutPermissionCheck(organization.getId())) + .assertNext(organization1 -> { + assertThat(organization1.getOrganizationConfiguration().getFeaturesWithPendingMigration()) + .hasSize(1); + assertThat(organization1.getOrganizationConfiguration().getMigrationStatus()) + .isEqualTo(IN_PROGRESS); + }) + .verifyComplete(); + } + + @Test + @WithUserDetails("api_user") + void updateOrganizationConfiguration_updateStrongPasswordPolicy_success() { + + // Ensure that the default organization does not have strong password policy setup + Mono organizationMono = organizationService.getDefaultOrganization(); + StepVerifier.create(organizationMono) + .assertNext(organization -> { + assertThat(organization.getOrganizationConfiguration().getIsStrongPasswordPolicyEnabled()) + .isNull(); + }) + .verifyComplete(); + + // Ensure that the strong password policy is enabled after the update + final OrganizationConfiguration changes = new OrganizationConfiguration(); + changes.setIsStrongPasswordPolicyEnabled(TRUE); + Mono resultMono = organizationService + .updateDefaultOrganizationConfiguration(changes) + .then(organizationService.getOrganizationConfiguration()) + .map(Organization::getOrganizationConfiguration); + + StepVerifier.create(resultMono) + .assertNext(organizationConfiguration -> { + assertThat(organizationConfiguration.getIsStrongPasswordPolicyEnabled()) + .isTrue(); + }) + .verifyComplete(); + + // Ensure that the strong password policy is disabled after the update + changes.setIsStrongPasswordPolicyEnabled(FALSE); + resultMono = organizationService + .updateDefaultOrganizationConfiguration(changes) + .then(organizationService.getOrganizationConfiguration()) + .map(Organization::getOrganizationConfiguration); + + StepVerifier.create(resultMono) + .assertNext(organizationConfiguration -> { + assertThat(organizationConfiguration.getIsStrongPasswordPolicyEnabled()) + .isFalse(); + }) + .verifyComplete(); + } + + /** + * This test checks that the organization cache is created and data is fetched without any deserialization errors + * This will ensure if any new nested user-defined classes are created in the organization object in the future, and + * implements serializable is missed for that class, the deserialization will fail leads this test to fail. + */ + @Test + @WithUserDetails(value = "api_user") + public void testDeserializationErrors() { + String organizationId = organizationService.getDefaultOrganizationId().block(); + Mono evictCachedOrganization = cacheableRepositoryHelper.evictCachedOrganization(organizationId); + Mono hasKeyMono = reactiveRedisTemplate.hasKey("organization:" + organizationId); + Mono organizationMono = organizationService.getDefaultOrganization(); + StepVerifier.create(evictCachedOrganization.then(organizationMono).then(hasKeyMono)) + .assertNext(Assertions::assertTrue) + .verifyComplete(); + } +} diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/TenantServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/TenantServiceCETest.java deleted file mode 100644 index f82b882de984..000000000000 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/TenantServiceCETest.java +++ /dev/null @@ -1,400 +0,0 @@ -package com.appsmith.server.services.ce; - -import com.appsmith.caching.components.CacheManager; -import com.appsmith.external.enums.FeatureFlagEnum; -import com.appsmith.server.constants.FeatureMigrationType; -import com.appsmith.server.constants.LicensePlan; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; -import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.helpers.FeatureFlagMigrationHelper; -import com.appsmith.server.helpers.UserUtils; -import com.appsmith.server.helpers.ce.bridge.Bridge; -import com.appsmith.server.repositories.CacheableRepositoryHelper; -import com.appsmith.server.repositories.TenantRepository; -import com.appsmith.server.repositories.UserRepository; -import com.appsmith.server.services.FeatureFlagService; -import com.appsmith.server.services.TenantService; -import com.appsmith.server.solutions.EnvManager; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.data.redis.core.ReactiveRedisTemplate; -import org.springframework.security.test.context.support.WithUserDetails; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; -import static com.appsmith.external.enums.FeatureFlagEnum.TEST_FEATURE_2; -import static com.appsmith.server.constants.MigrationStatus.COMPLETED; -import static com.appsmith.server.constants.MigrationStatus.IN_PROGRESS; -import static com.appsmith.server.exceptions.AppsmithErrorCode.FEATURE_FLAG_MIGRATION_FAILURE; -import static java.lang.Boolean.FALSE; -import static java.lang.Boolean.TRUE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; - -@SpringBootTest -class TenantServiceCETest { - - @Autowired - TenantService tenantService; - - @MockBean - EnvManager envManager; - - @Autowired - UserRepository userRepository; - - @Autowired - TenantRepository tenantRepository; - - @Autowired - UserUtils userUtils; - - @SpyBean - FeatureFlagService featureFlagService; - - @Autowired - ReactiveRedisTemplate reactiveRedisTemplate; - - @SpyBean - CacheManager cacheManager; - - @SpyBean - CacheableRepositoryHelper cacheableRepositoryHelper; - - @MockBean - FeatureFlagMigrationHelper featureFlagMigrationHelper; - - TenantConfiguration originalTenantConfiguration; - - @BeforeEach - public void setup() throws IOException { - final Tenant tenant = tenantService.getDefaultTenant().block(); - assert tenant != null; - originalTenantConfiguration = tenant.getTenantConfiguration(); - - tenantRepository - .updateAndReturn(tenant.getId(), Bridge.update().set(Tenant.Fields.tenantConfiguration, null), null) - .block(); - - // Make api_user super-user to test tenant admin functionality - // Todo change this to tenant admin once we introduce multitenancy - userRepository - .findByEmail("api_user") - .flatMap(user -> userUtils.makeSuperUser(List.of(user))) - .block(); - doReturn(Mono.empty()).when(cacheManager).get(anyString(), anyString()); - } - - @AfterEach - public void cleanup() { - Tenant updatedTenant = new Tenant(); - updatedTenant.setTenantConfiguration(originalTenantConfiguration); - tenantService - .getDefaultTenantId() - .flatMap(tenantId -> tenantService.update(tenantId, updatedTenant)) - .doOnError(error -> { - System.err.println("Error during cleanup: " + error.getMessage()); - }) - .block(); - } - - @Test - void ensureMapsKey() { - StepVerifier.create(tenantService.getTenantConfiguration()) - .assertNext(tenant -> { - assertThat(tenant.getTenantConfiguration().getGoogleMapsKey()) - .isNull(); - }) - .verifyComplete(); - } - - @Test - @WithUserDetails("api_user") - void setMapsKeyAndGetItBack() { - final TenantConfiguration changes = new TenantConfiguration(); - changes.setGoogleMapsKey("test-key"); - - final Mono resultMono = - tenantService.updateDefaultTenantConfiguration(changes).map(Tenant::getTenantConfiguration); - - StepVerifier.create(resultMono) - .assertNext(tenantConfiguration -> { - assertThat(tenantConfiguration.getGoogleMapsKey()).isEqualTo("test-key"); - }) - .verifyComplete(); - } - - @Test - void setMapsKeyWithoutAuthentication() { - final TenantConfiguration changes = new TenantConfiguration(); - changes.setGoogleMapsKey("test-key"); - - final Mono resultMono = tenantService.updateDefaultTenantConfiguration(changes); - - StepVerifier.create(resultMono) - .expectErrorMatches(error -> { - assertThat(error.getMessage()).startsWith("Unable to find tenant "); - return true; - }) - .verify(); - } - - @Test - @WithUserDetails("usertest@usertest.com") - void setMapsKeyWithoutAuthorization() { - final TenantConfiguration changes = new TenantConfiguration(); - changes.setGoogleMapsKey("test-key"); - - final Mono resultMono = tenantService.updateDefaultTenantConfiguration(changes); - - StepVerifier.create(resultMono) - .expectErrorMatches(error -> { - assertThat(error.getMessage()).startsWith("Unable to find tenant "); - return true; - }) - .verify(); - } - - @Test - @WithUserDetails("anonymousUser") - void getTenantConfig_Valid_AnonymousUser() { - StepVerifier.create(tenantService.getTenantConfiguration()) - .assertNext(tenant -> { - assertThat(tenant.getTenantConfiguration()).isNotNull(); - assertThat(tenant.getTenantConfiguration().getLicense()).isNotNull(); - assertThat(tenant.getTenantConfiguration().getLicense().getPlan()) - .isEqualTo(LicensePlan.FREE); - }) - .verifyComplete(); - } - - @Test - @WithUserDetails("api_user") - void setEmailVerificationEnabled_WithInvalidSMTPHost_ReturnsError() { - final TenantConfiguration changes = new TenantConfiguration(); - changes.setEmailVerificationEnabled(TRUE); - - Map envVars = new HashMap<>(); - // adding invalid mail host - envVars.put("APPSMITH_MAIL_HOST", ""); - - // mocking env vars file - Mockito.when(envManager.getAllNonEmpty()).thenReturn(Mono.just(envVars)); - - final Mono resultMono = tenantService - .updateDefaultTenantConfiguration(changes) - .then(tenantService.getTenantConfiguration()) - .map(Tenant::getTenantConfiguration); - - StepVerifier.create(resultMono) - .expectErrorMatches(error -> { - assertThat(error.getMessage()).startsWith("Your SMTP configuration is invalid"); - return true; - }) - .verify(); - } - - @Test - @WithUserDetails("api_user") - void setEmailVerificationEnabled_WithValidSMTPHost_Success() { - final TenantConfiguration changes = new TenantConfiguration(); - changes.setEmailVerificationEnabled(TRUE); - - Map envVars = new HashMap<>(); - // adding valid mail host - envVars.put("APPSMITH_MAIL_HOST", "smtp.sendgrid.net"); - - // mocking env vars file - Mockito.when(envManager.getAllNonEmpty()).thenReturn(Mono.just(envVars)); - - final Mono resultMono = tenantService - .updateDefaultTenantConfiguration(changes) - .then(tenantService.getTenantConfiguration()) - .map(Tenant::getTenantConfiguration); - - StepVerifier.create(resultMono) - .assertNext(tenantConfiguration -> { - assertThat(tenantConfiguration.isEmailVerificationEnabled()).isTrue(); - }) - .verifyComplete(); - } - - @Test - @WithUserDetails("api_user") - void setEmailVerificationEnabledFalseAndGetItBack() { - final TenantConfiguration changes = new TenantConfiguration(); - changes.setEmailVerificationEnabled(Boolean.FALSE); - - final Mono resultMono = tenantService - .updateDefaultTenantConfiguration(changes) - .then(tenantService.getTenantConfiguration()) - .map(Tenant::getTenantConfiguration); - - StepVerifier.create(resultMono) - .assertNext(tenantConfiguration -> { - assertThat(tenantConfiguration.isEmailVerificationEnabled()).isFalse(); - }) - .verifyComplete(); - } - - @Test - void checkAndExecuteMigrationsForTenantFeatureFlags_emptyMigrationMap_revertSameTenant() { - Mockito.when(featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(any(), any())) - .thenReturn(Mono.just(TRUE)); - - Tenant tenant = new Tenant(); - tenant.setId(UUID.randomUUID().toString()); - TenantConfiguration config = new TenantConfiguration(); - config.setFeaturesWithPendingMigration(new HashMap<>()); - tenant.setTenantConfiguration(config); - final Mono resultMono = tenantService.checkAndExecuteMigrationsForTenantFeatureFlags(tenant); - StepVerifier.create(resultMono) - .assertNext(tenant1 -> { - assertThat(tenant1).isEqualTo(tenant); - assertThat(tenant1.getTenantConfiguration().getFeaturesWithPendingMigration()) - .isEmpty(); - assertThat(tenant1.getTenantConfiguration().getMigrationStatus()) - .isEqualTo(COMPLETED); - }) - .verifyComplete(); - } - - @Test - void checkAndExecuteMigrationsForTenantFeatureFlags_withPendingMigration_getUpdatedTenant() { - Mockito.when(featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(any(), any())) - .thenReturn(Mono.just(TRUE)); - - Tenant tenant = new Tenant(); - tenant.setId(UUID.randomUUID().toString()); - TenantConfiguration config = new TenantConfiguration(); - Map featureMigrationTypeMap = new HashMap<>(); - config.setFeaturesWithPendingMigration(featureMigrationTypeMap); - featureMigrationTypeMap.put(TENANT_TEST_FEATURE, FeatureMigrationType.ENABLE); - featureMigrationTypeMap.put(TEST_FEATURE_2, FeatureMigrationType.DISABLE); - tenant.setTenantConfiguration(config); - final Mono resultMono = tenantService.checkAndExecuteMigrationsForTenantFeatureFlags(tenant); - StepVerifier.create(resultMono) - .assertNext(tenant1 -> { - assertThat(tenant1.getTenantConfiguration().getFeaturesWithPendingMigration()) - .isEmpty(); - assertThat(tenant1.getTenantConfiguration().getMigrationStatus()) - .isEqualTo(COMPLETED); - }) - .verifyComplete(); - } - - @Test - @WithUserDetails("api_user") - void - checkAndExecuteMigrationsForTenantFeatureFlags_withPendingMigration_exceptionWhileRunningMigration_getUpdatedTenant() { - Mockito.when(featureFlagMigrationHelper.checkAndExecuteMigrationsForFeatureFlag(any(), any())) - .thenReturn(Mono.just(TRUE)) - .thenReturn(Mono.just(FALSE)); - - Tenant tenant = new Tenant(); - tenant.setId(UUID.randomUUID().toString()); - TenantConfiguration config = new TenantConfiguration(); - Map featureMigrationTypeMap = new HashMap<>(); - config.setFeaturesWithPendingMigration(featureMigrationTypeMap); - featureMigrationTypeMap.put(TENANT_TEST_FEATURE, FeatureMigrationType.DISABLE); - featureMigrationTypeMap.put(TEST_FEATURE_2, FeatureMigrationType.ENABLE); - tenant.setTenantConfiguration(config); - final Mono resultMono = tenantService.checkAndExecuteMigrationsForTenantFeatureFlags(tenant); - - // Verify that the feature flag migration failure is thrown - StepVerifier.create(resultMono) - .expectErrorSatisfies(throwable -> { - assertThat(throwable instanceof AppsmithException).isTrue(); - assertThat(((AppsmithException) throwable).getAppErrorCode()) - .isEqualTo(FEATURE_FLAG_MIGRATION_FAILURE.getCode()); - }) - .verify(); - - // Verify that the tenant is updated for the feature flag migration failure - StepVerifier.create(tenantService.getByIdWithoutPermissionCheck(tenant.getId())) - .assertNext(updatedTenant -> { - assertThat(updatedTenant.getTenantConfiguration().getFeaturesWithPendingMigration()) - .hasSize(1); - assertThat(updatedTenant.getTenantConfiguration().getMigrationStatus()) - .isEqualTo(IN_PROGRESS); - }) - .verifyComplete(); - } - - @Test - @WithUserDetails("api_user") - void updateTenantConfiguration_updateStrongPasswordPolicy_success() { - - // Ensure that the default tenant does not have strong password policy setup - Mono tenantMono = tenantService.getDefaultTenant(); - StepVerifier.create(tenantMono) - .assertNext(tenant -> { - assertThat(tenant.getTenantConfiguration().getIsStrongPasswordPolicyEnabled()) - .isNull(); - }) - .verifyComplete(); - - // Ensure that the strong password policy is enabled after the update - final TenantConfiguration changes = new TenantConfiguration(); - changes.setIsStrongPasswordPolicyEnabled(TRUE); - Mono resultMono = tenantService - .updateDefaultTenantConfiguration(changes) - .then(tenantService.getTenantConfiguration()) - .map(Tenant::getTenantConfiguration); - - StepVerifier.create(resultMono) - .assertNext(tenantConfiguration -> { - assertThat(tenantConfiguration.getIsStrongPasswordPolicyEnabled()) - .isTrue(); - }) - .verifyComplete(); - - // Ensure that the strong password policy is disabled after the update - changes.setIsStrongPasswordPolicyEnabled(FALSE); - resultMono = tenantService - .updateDefaultTenantConfiguration(changes) - .then(tenantService.getTenantConfiguration()) - .map(Tenant::getTenantConfiguration); - - StepVerifier.create(resultMono) - .assertNext(tenantConfiguration -> { - assertThat(tenantConfiguration.getIsStrongPasswordPolicyEnabled()) - .isFalse(); - }) - .verifyComplete(); - } - - /** - * This test checks that the tenant cache is created and data is fetched without any deserialization errors - * This will ensure if any new nested user-defined classes are created in the tenant object in the future, and - * implements serializable is missed for that class, the deserialization will fail leads this test to fail. - */ - @Test - @WithUserDetails(value = "api_user") - public void testDeserializationErrors() { - String tenantId = tenantService.getDefaultTenantId().block(); - Mono evictTenantCache = cacheableRepositoryHelper.evictCachedTenant(tenantId); - Mono hasKeyMono = reactiveRedisTemplate.hasKey("tenant:" + tenantId); - Mono cachedTenant = tenantService.getDefaultTenant(); - StepVerifier.create(evictTenantCache.then(cachedTenant).then(hasKeyMono)) - .assertNext(Assertions::assertTrue) - .verifyComplete(); - } -} diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/EnvManagerTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/EnvManagerTest.java index 05d302d4d203..5bcb12f37009 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/EnvManagerTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/EnvManagerTest.java @@ -14,9 +14,9 @@ import com.appsmith.server.services.AssetService; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.EmailService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.PermissionGroupService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserService; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; @@ -81,7 +81,7 @@ public class EnvManagerTest { private UserUtils userUtils; @MockBean - private TenantService tenantService; + private OrganizationService organizationService; @MockBean private ObjectMapper objectMapper; @@ -108,7 +108,7 @@ public void setup() { permissionGroupService, configService, userUtils, - tenantService, + organizationService, objectMapper, emailService); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/PartialImportServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/PartialImportServiceTest.java index 1169d8742880..646d60b177b2 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/PartialImportServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/PartialImportServiceTest.java @@ -37,6 +37,7 @@ import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.WorkspaceService; import com.google.gson.Gson; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,19 +46,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; -import org.springframework.http.MediaType; -import org.springframework.http.codec.multipart.FilePart; -import org.springframework.http.codec.multipart.Part; +import org.springframework.core.io.DefaultResourceLoader; import org.springframework.security.test.context.support.WithUserDetails; -import reactor.core.publisher.Flux; +import org.springframework.util.StreamUtils; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import reactor.util.function.Tuple3; +import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.HashMap; import java.util.List; @@ -252,16 +248,10 @@ private Application createGitConnectedApp(String applicationName) { .block(); } - private FilePart createFilePart(String filePath) { - FilePart filepart = Mockito.mock(FilePart.class, Mockito.RETURNS_DEEP_STUBS); - Flux dataBufferFlux = DataBufferUtils.read( - new ClassPathResource(filePath), new DefaultDataBufferFactory(), 4096) - .cache(); - - Mockito.when(filepart.content()).thenReturn(dataBufferFlux); - Mockito.when(filepart.headers().getContentType()).thenReturn(MediaType.APPLICATION_JSON); - - return filepart; + @SneakyThrows + private String readResource(String filePath) { + return StreamUtils.copyToString( + new DefaultResourceLoader().getResource(filePath).getInputStream(), StandardCharsets.UTF_8); } @Test @@ -282,10 +272,10 @@ public void testPartialImport_nonGitConnectedApp_success() { .block() .getId(); - Part filePart = createFilePart("test_assets/ImportExportServiceTest/partial-export-resource.json"); + String jsonContents = readResource("test_assets/ImportExportServiceTest/partial-export-resource.json"); Mono, List>> result = partialImportService - .importResourceInPage(workspaceId, testApplication.getId(), pageId, null, filePart) + .importResourceInPage(workspaceId, testApplication.getId(), pageId, jsonContents) .flatMap(application -> { Mono> actionList = newActionService .findByPageId(pageId, Optional.empty()) @@ -334,11 +324,12 @@ public void testPartialImport_gitConnectedAppDefaultBranch_success() { savedPage.setRefName("master"); savedPage = applicationPageService.createPage(savedPage).block(); - Part filePart = createFilePart("test_assets/ImportExportServiceTest/partial-export-valid-without-widget.json"); + String jsonContents = + readResource("test_assets/ImportExportServiceTest/partial-export-valid-without-widget.json"); PageDTO finalSavedPage = savedPage; Mono, List>> result = partialImportService - .importResourceInPage(workspaceId, application.getId(), savedPage.getId(), "master", filePart) + .importResourceInPage(workspaceId, application.getId(), savedPage.getId(), jsonContents) .flatMap(application1 -> { Mono> actionList = newActionService .findByPageId(finalSavedPage.getId(), Optional.empty()) @@ -395,12 +386,12 @@ public void testPartialImport_nameClashInAction_successWithNoNameDuplicates() { .block() .getId(); - Part filePart = createFilePart("test_assets/ImportExportServiceTest/partial-export-resource.json"); + String jsonContents = readResource("test_assets/ImportExportServiceTest/partial-export-resource.json"); Mono, List>> result = partialImportService - .importResourceInPage(workspaceId, testApplication.getId(), pageId, null, filePart) + .importResourceInPage(workspaceId, testApplication.getId(), pageId, jsonContents) .then(partialImportService.importResourceInPage( - workspaceId, testApplication.getId(), pageId, null, filePart)) + workspaceId, testApplication.getId(), pageId, jsonContents)) .flatMap(application -> { Mono> actionList = newActionService .findByPageId(pageId, Optional.empty()) @@ -450,15 +441,15 @@ public void testPartialImport_nameClashInAction_successWithNoNameDuplicates() { @WithUserDetails(value = "api_user") public void testPartialImportWithBuildingBlock_nameClash_success() { - Part filePart = createFilePart("test_assets/ImportExportServiceTest/building-block.json"); + String jsonContents = readResource("test_assets/ImportExportServiceTest/building-block.json"); ApplicationJson applicationJson = (ApplicationJson) - importService.extractArtifactExchangeJson(filePart).block(); + importService.extractArtifactExchangeJson(jsonContents).block(); // Mock the call to fetch the json file from CS Mockito.when(applicationTemplateService.getApplicationJsonFromTemplate("templatedId")) .thenReturn(Mono.just(applicationJson)); ApplicationJson applicationJson1 = (ApplicationJson) - importService.extractArtifactExchangeJson(filePart).block(); + importService.extractArtifactExchangeJson(jsonContents).block(); Mockito.when(applicationTemplateService.getApplicationJsonFromTemplate("templatedId1")) .thenReturn(Mono.just(applicationJson1)); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/UserSignupTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/UserSignupTest.java index b00c0e0bd6c9..f47afc744b59 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/UserSignupTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/UserSignupTest.java @@ -1,8 +1,8 @@ package com.appsmith.server.solutions; import com.appsmith.server.authentication.handlers.AuthenticationSuccessHandler; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.domains.Organization; +import com.appsmith.server.domains.OrganizationConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; @@ -12,7 +12,7 @@ import com.appsmith.server.services.CaptchaService; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.EmailService; -import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserService; import org.junit.jupiter.api.BeforeEach; @@ -64,11 +64,11 @@ public class UserSignupTest { private EmailService emailService; @MockBean - private TenantService tenantService; + private OrganizationService organizationService; private UserSignup userSignup; - private static Tenant tenant; + private static Organization organization; private static ServerWebExchange exchange; @@ -85,15 +85,15 @@ public void setup() { userUtils, networkUtils, emailService, - tenantService); + organizationService); exchange = Mockito.mock(ServerWebExchange.class); Mockito.when(exchange.getSession()).thenReturn(Mono.just(new MockWebSession())); - tenant = new Tenant(); - TenantConfiguration configuration = new TenantConfiguration(); - tenant.setTenantConfiguration(configuration); - Mockito.when(tenantService.getDefaultTenant()).thenReturn(Mono.just(tenant)); + organization = new Organization(); + OrganizationConfiguration configuration = new OrganizationConfiguration(); + organization.setOrganizationConfiguration(configuration); + Mockito.when(organizationService.getDefaultOrganization()).thenReturn(Mono.just(organization)); } private String createRandomString(int length) { @@ -141,8 +141,8 @@ public void signupAndLogin_whenStrongPasswordRequirementEnabled_whenPasswordIsWe user.setEmail("testemail@test123.com"); user.setPassword(createRandomString(LOGIN_PASSWORD_MAX_LENGTH - 1)); - tenant.getTenantConfiguration().setIsStrongPasswordPolicyEnabled(true); - Mockito.when(tenantService.getDefaultTenant()).thenReturn(Mono.just(tenant)); + organization.getOrganizationConfiguration().setIsStrongPasswordPolicyEnabled(true); + Mockito.when(organizationService.getDefaultOrganization()).thenReturn(Mono.just(organization)); Mono userMono = userSignup.signupAndLogin(user, exchange); StepVerifier.create(userMono) .expectErrorSatisfies(throwable -> { @@ -154,6 +154,6 @@ public void signupAndLogin_whenStrongPasswordRequirementEnabled_whenPasswordIsWe }) .verify(); - tenant.getTenantConfiguration().setIsStrongPasswordPolicyEnabled(false); + organization.getOrganizationConfiguration().setIsStrongPasswordPolicyEnabled(false); } } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java index 0fc84add17f8..d1c1bfe57dd3 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java @@ -25,8 +25,8 @@ import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceContextService; import com.appsmith.server.services.FeatureFlagService; +import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; -import com.appsmith.server.services.TenantService; import com.appsmith.server.solutions.ActionPermission; import com.appsmith.server.solutions.DatasourcePermission; import com.appsmith.server.solutions.EnvironmentPermission; @@ -129,7 +129,7 @@ class ActionExecutionSolutionCEImplTest { ConfigService configService; @SpyBean - TenantService tenantService; + OrganizationService organizationService; @SpyBean CommonConfig commonConfig; @@ -169,7 +169,7 @@ public void beforeEach() { datasourceStorageService, environmentPermission, configService, - tenantService, + organizationService, commonConfig, actionExecutionSolutionHelper, featureFlagService);