Appbuilder sprint 5 merge main (#11573)

* statement timeout for postgresql mssql mysql can now be configured from env

* Enhance: Add clear all, cancel & apply functionality to TJDB filter-popup (#2344)

* Update filter inputs

* Update filter body

* Style fixes

* Handle invalid filters

* Fix bugs

* Feature: Add list all sheets and create new spreadsheet operation to GoogleSheets (#2370)

* Add create spreadsheet functionality

* Add list all sheets functionality

* Updated delete and batch-update methods

* Change interface to type

* Enhance: Add read documentation link with data source drop down in query builder (#2162)

* Add read-documentation link

* Change copywriting for datasources name

* Update new component for link

* Increase input width

Update redshift link

* Fix the datasource name issue

* Enhance: Improve error handling in Google-Sheets run query (#2286)

* Add error details

* Display error for incorrect JSON

* Throw error for empty spreadsheetid and operator

* Enhance: Error handling for PgSql, MySql and MsSql (#2389)

* Enhance error handling for pgsql

* Enhance error handling for mysql

* Remove console logs

* Enhance error handling for MsSql

* Refactor error handling for consistency

* Enhance: Rest api body to accept raw input instead of raw json. (#2249)

* Enhanced rest api body to accept raw input instead of raw json.

* Changed content type from application/json to text/json and changed copywrite to RAW.

* Changed rest api body toggle label from 'RAW' to 'Raw'.

* Added request label for static REST API data source.

* Fixed issue where GET query failed since body was undefined.

* Integrated json_body to add backward compatibility.

* Removed console logs.

* Added support for 'text/json' type in checkIfContentTypeIsJson function.

* Made changes according to new frontend architecture in v3.

* Fixed request URL field overflow issue.

---------

Co-authored-by: Akshay Sasidharan <akshaysasidharan93@gmail.com>

* Feature: Add SSL support to MongoDB datasource (#2430)

* Add TLS support inputs in frontend

* Add backend logic for TLS support

* Add TLS inputs types

* Update TLS label

* Change ssl_certificate to tls_certificate

* Update the file handling in tls

* Update connection logic

* Fix unlinking file issue

* Remove catch block for unlinking file

* Handle tls certs directly

* Feature: Stripe plugin UI fixes with OpenAPI endpoint as source (#2725)

* Fixed GET and DELETE request input renders and added all UX fixes (#9498)

* fixed get and delete request input renders and added all UX fixes

* Extracted Stripe plugin component as a separate component for Dynamic Form.

* Resolved PR review comments and fixed issue where rendering path input field crashed the app.

* Changed param name underline to dashed for tooltip and revamped input field clear button

* Fixed a few sonarlint issues.

* Removed the duplicate code by creating a separate function named RenderParameterFields.

* Refactored computeOperationSelectionOptions function to not nest functions more than 4 levels deep.

* Refactored RenderParameterFields function to reduce its Cognitive Complexity.

* Made span tag with the 'button' interactive role focusable.

* Inside switch case for codehinter in DynamicForm > getElementProps, Extracted nested ternary operation for theme into an independent statement.

* Added keyboard listener to the clear button.

* Removed opacity from select dropdown and operation from operation select dropdown UI.

* Fixed syntax error in clearButton function.

* Removed the package @nrwl/nx-linux-x64-gnu from marketplace dependencies.

---------

Co-authored-by: Mansukh Kaur <mansukhkaur@Mansukhs-MacBook-Pro.local>
Co-authored-by: Devanshu Rastogi <devanshu.rastogi05@gmail.com>

* Made changes according to new app builder architecture in v3.

* Fixed import issue for codehintor

* Fixed issue where due to incorrect value, stripe queries crashed the entire app.

---------

Co-authored-by: Mansukh Kaur <mansukhkaur@Mansukhs-MacBook-Pro.local>
Co-authored-by: Devanshu Rastogi <devanshu.rastogi05@gmail.com>

* Enhance: Improve error handling in Airtable run query (#2234)

* Refactor error handling to streamline QueryError messages

* Handle 404 errors

* Enhance: Add AI-tag to datasources in marketplace page (#2597)

* Add AI-tag to datasources in marketplace page

* AI BANNER Tag

* margin

* Refactor tag rendering logic for marketplace page

* Refactor tag rendering for datasource page

* Refactor import and props

* Remove ai prefix and fix indentations

* Make custom hook for fetching plugins.json

* Add AI tag on installed page

* Marketplace page UI fix and add a plugin button fixes

* Add AI tag on datasource connection form

Change classname

* Fix svg flickering

* Fix svg chipping issue

* Push AI tag to extreme right

---------

Co-authored-by: Rudra <rudra21ultra@gmail.com>

* Fix: Api call for token generation in client-credentials grant type (#2785)

* fix: query kind for select source in rest api

* Fix: ToolJet database limit check API issue (#11416)

* bump to v3.0.5-ce

* Added data-cy for newly added components (#11435)

* Modified failed Platform cypress test cases for Tooljet V3 (#11486)

* Modify platform cypress test cases

* Added cypress test cases for user onboarding flow (#11499)

* Add data-cy for newly added components

* Add data-cy for onboarding page elements

* Modify failed test cases

* Adding more cases

* Modify onboarding test cases

* Modify user invite flow

* chnages on onboarding test scripts

* revert the changes

* revert the changes

* removed .only form profile file

* resolved review changes

---------

Co-authored-by: ajith-k-v <ajith.jaban@gmail.com>
Co-authored-by: Sri mani Teja s <mani@Sris-MacBook-Pro-4.local>

* fix: Fixes broken loading state for container

* update cypress workflow for subpath

* Add data-cy for workspace constants components (#11530)

* fix table down load event not showing up

* Hotfix: The build failed to include the reference file for custom validation of the ToolJet database schema. (#11490)

* tooljet database schema custom validation reference file was not included in the build

* fix: missed a dependency for copyfiles

* change version to 3.1.0

---------

Co-authored-by: Ganesh Kumar <ganesh8056234@gmail.com>
Co-authored-by: Parth <108089718+parthy007@users.noreply.github.com>
Co-authored-by: Devanshu Rastogi <devanshu.rastogi05@gmail.com>
Co-authored-by: Akshay Sasidharan <akshaysasidharan93@gmail.com>
Co-authored-by: Mansukh Kaur <mansukhkaur@Mansukhs-MacBook-Pro.local>
Co-authored-by: Rudra <rudra21ultra@gmail.com>
Co-authored-by: Vijaykant Yadav <vjy239@gmail.com>
Co-authored-by: Ganesh Kumar <40178541+ganesh8056@users.noreply.github.com>
Co-authored-by: Ajith KV <ajith.jaban@gmail.com>
Co-authored-by: Adish M <44204658+adishM98@users.noreply.github.com>
Co-authored-by: Srimanitejas123 <mani@tooljet.com>
Co-authored-by: Sri mani Teja s <mani@Sris-MacBook-Pro-4.local>
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
Co-authored-by: Kartik Gupta <gupta.kartik18kg@gmail.com>
This commit is contained in:
Johnson Cherian 2024-12-10 12:21:34 +05:30 committed by GitHub
parent 3bf422d3cc
commit 97fb315019
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
131 changed files with 4444 additions and 4804 deletions

View file

@ -212,7 +212,7 @@ jobs:
uses: jsdaniell/create-json@1.1.2
with:
name: "cypress.env.json"
json: ${{ secrets.CYPRESS_SECRETS }}
json: ${{ secrets.CYPRESS_SECRETS_SUBPATH }}
dir: "./cypress-tests"
- name: Platform-subpath

View file

@ -1 +1 @@
3.2.4-ce
3.2.0-ce

View file

@ -82,7 +82,7 @@ module.exports = defineConfig({
experimentalModfyObstructiveThirdPartyCode: true,
experimentalRunAllSpecs: true,
baseUrl: "http://localhost:8082",
specPattern: "cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js",
specPattern: "cypress/e2e/happyPath/platform/**/**/*.cy.js",
downloadsFolder: "cypress/downloads",
numTestsKeptInMemory: 0,
redirectionLimit: 10,

View file

@ -7,7 +7,7 @@ Cypress.Commands.add(
redirection = "/"
) => {
cy.request({
url: `http://localhost:3000/api/authenticate/${workspaceId}`,
url: `${Cypress.env("server_host")}/api/authenticate/${workspaceId}`,
method: "POST",
body: {
email: userEmail,
@ -69,7 +69,7 @@ Cypress.Commands.add("apiCreateApp", (appName = "testApp") => {
Cypress.env("authToken", `tj_auth_token=${cookie.value}`);
cy.request({
method: "POST",
url: "http://localhost:3000/api/apps",
url: `${Cypress.env("server_host")}/api/apps`,
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token = ${cookie.value}`,
@ -103,7 +103,7 @@ Cypress.Commands.add("apiDeleteApp", (appId = Cypress.env("appId")) => {
cy.request(
{
method: "DELETE",
url: `http://localhost:3000/api/apps/${Cypress.env("appId")}`,
url: `${Cypress.env("server_host")}/api/apps/${Cypress.env("appId")}`,
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: Cypress.env("authToken"),
@ -140,7 +140,7 @@ Cypress.Commands.add("apiCreateWorkspace", (workspaceName, workspaceSlug) => {
cy.request(
{
method: "POST",
url: "http://localhost:3000/api/organizations",
url: `${Cypress.env("server_host")}/api/organizations`,
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
@ -162,7 +162,7 @@ Cypress.Commands.add("logoutApi", () => {
cy.request(
{
method: "GET",
url: "http://localhost:3000/api/logout",
url: `${Cypress.env("server_host")}/api/logout`,
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
@ -180,7 +180,7 @@ Cypress.Commands.add("userInviteApi", (userName, userEmail) => {
cy.request(
{
method: "POST",
url: "http://localhost:3000/api/organization_users",
url: `${Cypress.env("server_host")}/api/organization_users`,
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
@ -207,7 +207,7 @@ Cypress.Commands.add("addQueryApi", (queryName, query, dataQueryId) => {
};
cy.request({
method: "PATCH",
url: `http://localhost:3000/api/data_queries/${dataQueryId}`,
url: `${Cypress.env("server_host")}/api/data_queries/${dataQueryId}`,
headers: headers,
body: {
name: queryName,
@ -234,7 +234,7 @@ Cypress.Commands.add(
cy.request({
method: "GET",
url: `http://localhost:3000/api/apps/${appId}`,
url: `${Cypress.env("server_host")}/api/apps/${appId}`,
headers: {
"Tj-Workspace-Id": workspaceId,
Cookie: `${authToken}; app_id=${appId}`,
@ -246,7 +246,7 @@ Cypress.Commands.add(
cy.request({
method: "POST",
url: "http://localhost:3000/api/data_queries",
url: `${Cypress.env("server_host")}/api/data_queries`,
headers: {
"Content-Type": "application/json",
Cookie: authToken,
@ -273,3 +273,141 @@ Cypress.Commands.add(
});
}
);
// Cypress.Commands.add("addComponentToApp", (appName, componentName, layoutConfig = {}) => {
// cy.task("updateId", {
// dbconfig: Cypress.env("app_db"),
// sql: `select id from apps where name='${appName}';`,
// }).then((resp) => {
// appId = resp.rows[0]id;
// // Default layout values
// const defaultLayout = {
// desktop: { top: 90, left: 9, width: 6, height: 40 },
// mobile: { top: 90, left: 9, width: 6, height: 40 },
// };
// // Merge default layout with the provided configuration
// const layouts = {
// desktop: { ...defaultLayout.desktop, ...layoutConfig.desktop },
// mobile: { ...defaultLayout.mobile, ...layoutConfig.mobile },
// };
// cy.getCookie("tj_auth_token", { log: false }).then((cookie) => {
// Cypress.env("authToken", `tj_auth_token=${cookie.value}`);
// cy.request({
// method: "GET",
// url: `${Cypress.env("server_host")}/api/v2/apps/${appId}`,
// headers: {
// "Tj-Workspace-Id": Cypress.env("workspaceId"),
// Cookie: `tj_auth_token=${cookie.value}`,
// },
// }).then((response) => {
// expect(response.status).to.eq(200);
// const { id: editingVersionId, home_page_id: homePageId } = response.body.editing_version;
// const componentId = crypto.randomUUID ? crypto.randomUUID() : require("uuid").v4();
// const requestBody = {
// is_user_switched_version: false,
// pageId: homePageId,
// diff: {
// [componentId]: {
// name: componentName,
// layouts: layouts,
// type: "Text",
// },
// },
// };
// cy.request({
// method: "POST",
// url: `${Cypress.env("server_host")}/api/v2/apps/$${appId}/versions/${editingVersionId}/components`,
// headers: {
// "Content-Type": "application/json",
// "Tj-Workspace-Id": Cypress.env("workspaceId"),
// Cookie: `tj_auth_token=${cookie.value}`,
// },
// body: requestBody,
// }).then((postResponse) => {
// expect(postResponse.status).to.eq(201);
// cy.log(`Component ${componentId} added successfully`);
// });
// });
// });
// });
// });
Cypress.Commands.add("addComponentToApp", (appName, componentName, layoutConfig = {}) => {
cy.task("updateId", {
dbconfig: Cypress.env("app_db"),
sql: `select id from apps where name='${appName}';`,
}).then((resp) => {
const appId = resp.rows[0]?.id; // Safely access the id field
if (!appId) {
throw new Error(`App ID not found for appName: ${appName}`);
}
// Default layout values
const defaultLayout = {
desktop: { top: 90, left: 9, width: 6, height: 40 },
mobile: { top: 90, left: 9, width: 6, height: 40 },
};
// Merge default layout with the provided configuration
const layouts = {
desktop: { ...defaultLayout.desktop, ...layoutConfig.desktop },
mobile: { ...defaultLayout.mobile, ...layoutConfig.mobile },
};
cy.getCookie("tj_auth_token", { log: false }).then((cookie) => {
Cypress.env("authToken", `tj_auth_token=${cookie.value}`);
cy.request({
method: "GET",
url: `${Cypress.env("server_host")}/api/v2/apps/${appId}`,
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
},
}).then((response) => {
expect(response.status).to.eq(200);
const { id: editingVersionId, home_page_id: homePageId } = response.body.editing_version;
const componentId = crypto.randomUUID ? crypto.randomUUID() : require("uuid").v4();
const requestBody = {
is_user_switched_version: false,
pageId: homePageId,
diff: {
[componentId]: {
name: componentName,
layouts: layouts,
type: "Text",
},
},
};
cy.request({
method: "POST",
url: `${Cypress.env("server_host")}/api/v2/apps/${appId}/versions/${editingVersionId}/components`,
headers: {
"Content-Type": "application/json",
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
},
body: requestBody,
}).then((postResponse) => {
expect(postResponse.status).to.eq(201);
cy.log(`Component ${componentId} added successfully`);
});
});
});
});
});

View file

@ -5,16 +5,23 @@ import { commonText, createBackspaceText } from "Texts/common";
import { passwordInputText } from "Texts/passwordInput";
import { importSelectors } from "Selectors/exportImport";
import { importText } from "Texts/exportImport";
import { onboardingSelectors } from "Selectors/onboarding";
Cypress.Commands.add(
"login",
"appUILogin",
(email = "dev@tooljet.io", password = "password") => {
cy.visit("/");
cy.clearAndType(commonSelectors.workEmailInputField, email);
cy.clearAndType(commonSelectors.passwordInputField, password);
cy.get(commonSelectors.signInButton).click();
cy.wait(2000);
cy.get(commonSelectors.homePageLogo).should("be.visible");
cy.wait(3000);
cy.clearAndType(onboardingSelectors.loginEmailInput, email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, password);
cy.get(onboardingSelectors.signInButton).click();
cy.intercept("GET", "api/library_apps").as(
"library_apps"
);
cy.get(commonSelectors.homePageLogo, { timeout: 10000 });
cy.wait("@library_apps");
}
);
@ -90,14 +97,6 @@ Cypress.Commands.add(
}
);
Cypress.Commands.add("appUILogin", () => {
cy.visit("/");
cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.signInButton).click();
cy.wait(2000);
cy.get(commonSelectors.homePageLogo).should("be.visible");
});
Cypress.Commands.add(
"clearAndTypeOnCodeMirror",
@ -365,11 +364,11 @@ Cypress.Commands.add("getPosition", (componentName) => {
Cypress.Commands.add("defaultWorkspaceLogin", () => {
cy.apiLogin();
cy.intercept("GET", "http://localhost:3000/api/library_apps").as(
cy.intercept("GET", "/api/library_apps").as(
"library_apps"
);
cy.visit("/my-workspace");
cy.get(commonSelectors.homePageLogo, { timeout: 10000 });
// cy.get(commonSelectors.homePageLogo, { timeout: 10000 });
cy.wait("@library_apps");
});

View file

@ -5,10 +5,10 @@ export const cyParamName = (paramName = "") => {
export const commonSelectors = {
toastMessage: ".go3958317564",
oldToastMessage: ".go318386747",
newToastMessage:
'.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551',
newToastMessage: '.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551 > .go3958317564',
toastCloseButton: '[data-cy="toast-close-button"]',
editButton: "[data-cy=edit-button]",
fileSelector: "[data-cy=uploaded-file-data]",
searchField: "[data-cy='widget-search-box-search-bar']",
firstWidget: "[data-cy=widget-list]:eq(0)",
canvas: "[data-cy=real-canvas]",
@ -21,9 +21,9 @@ export const commonSelectors = {
workEmailLabel: '[data-cy="work-email-label"]',
workEmailInputField: "[data-cy=work-email-input]",
emailInputError: '[data-cy="email-error-message"]',
passwordLabel: '[data-cy="password-label"]',
passwordLabel: '[data-cy="password-input-label"]',
forgotPasswordLink: '[data-cy="forgot-password-link"]',
passwordInputField: '[data-cy="password-input-field"]',
passwordInputField: '[data-cy="password-input-input"]',
signInButton: "[data-cy=login-button]",
loginButton: '[data-cy="login-button"]',
dropdown: "[data-cy=workspace-dropdown]",
@ -63,20 +63,21 @@ export const commonSelectors = {
workspaceLoginUrl: "[data-cy=workspace-login-url]",
workspaceName: '[data-cy="workspace-name"]:eq(0)',
signInHeader: '[data-cy="sign-in-header"]',
signInSubHeader: '[data-cy="sign-in-sub-header"]',
signInSubHeader: '[data-cy="signup-info"]',
createAnAccountLink: '[data-cy="create-an-account-link"]',
SignUpSectionHeader: '[data-cy="signup-section-header"]',
signUpSectionHeader: '[data-cy="sign-up-header"]',
signInRedirectText: '[data-cy="signin-redirect-text"]',
signInRedirectLink: '[data-cy="signin-redirect-link"]',
signInRedirectLink: '[data-cy="signin-link"]',
signUpTermsHelperText: '[data-cy="signup-terms-helper"]',
termsOfServiceLink: '[data-cy="terms-of-service-link"]',
privacyPolicyLink: '[data-cy="privacy-policy-link"]',
redirectURL: '[data-cy="redirect-url"]',
invitePageHeader: '[data-cy="invite-page-header"]',
invitePageSubHeader: '[data-cy="invite-page-sub-header"]',
invitePageHeader: '[data-cy="join-my-workspace-header"]',
invitePageSubHeader: '[data-cy="onboarding-page-description"]',
userNameInputLabel: '[data-cy="name-input-label"]',
invitedUserName: '[data-cy="invited-user-name"]',
invitedUserEmail: '[data-cy="invited-user-email"]',
invitedUserName: '[data-cy="name-input-input-value"]',
invitedUserEmail: '[data-cy="email-input-value"]',
invitedUseremail: '[data-cy="email-input-input-value"]',
acceptInviteButton: '[data-cy="accept-invite-button"]',
databaseIcon: '[data-cy="icon-database"]',
profileSettings: '[data-cy="profile-settings"]',
@ -108,6 +109,9 @@ export const commonSelectors = {
exportAllButton: '[data-cy="export-all-button"]',
avatarImage: '[data-cy="avatar-image"]',
selfHostSetUpBanner: '[data-cy="setup-banner-inner"]',
HostBanner: '[data-cy="onboarding-image"]',
adminSetup: '[data-cy="set-up-your-admin-account-header"]',
signupTerms: '[data-cy="signup-terms-helper"]',
selfHostSetUpSubBanner: '[data-cy="setup-sub-banner"]',
selfHostSetUpCard: '[data-cy="setup-card"]',
selfHostSetUpCardImage: '[data-cy="setup-card-image"]',
@ -115,52 +119,58 @@ export const commonSelectors = {
selfHostSetUpCardSubHeader: '[data-cy="setup-card-sub-header"]',
setUpToolJetButton: '[data-cy="setup-tooljet-button"]',
setUpadminCheckPoint: '[data-cy="set-up-admin-check-point"]',
setUpworkspaceCheckPoint: '[data-cy="set-up-workspace-check-point"]',
setUpworkspaceCheckPoint: '[data-cy="set-up-your-workspace!-header"]',
companyProfileCheckPoint: '[data-cy="company-profile-check-point"]',
onboardingPageHeader: '[data-cy="onboarding-page-header"]',
onboardingPageSubHeader: '[data-cy="onboarding-page-sub-header"]',
onboardingPageDescription: '[data-cy="onboarding-page-description"]',
passwordHelperText: '[data-cy="password-helper-text"]',
passwordHelperText: '[data-cy="new-password-input-hint"]',
continueButton: '[data-cy="continue-button"]',
passwordHelperTextSignup: '[data-cy="password-input-hint"]',
continueButton: '[data-cy="sign-up-button"]',
OnbordingContinue: '[data-cy="onboarding-submit-button"]',
userAccountNameAvatar: '[data-cy="user-account-name-avatar"]',
workspaceNameInputLabel: '[data-cy="workspace-name-input-label"]',
workspaceNameInputField: '[data-cy="workspace-name-input-field"]',
workspaceNameInputLabel: '[data-cy="onboarding-workspace-name-label"]',
workspaceNameInputField: '[data-cy="onboarding-workspace-name-input"]',
backArrow: '[data-cy="back-arrow"]',
backArrowText: '[data-cy="back-arrow-text"]',
onboardingPorgressBubble: '[data-cy="onboarding-progress-bubbles"]',
skipArrow: '[data-cy="skip-button"]',
skipArrowText: '[data-cy="skip-arrow-text"]',
companyNameInputField: '[data-cy="company-name-input-field"]',
nameInputField: '[data-cy="name-input-field"]',
emailInputField: '[data-cy="email-input-field"]',
nameInputField: '[data-cy="name-input-input"]',
emailInputField: '[data-cy="email-input-input"]',
skipbutton: '[class="driver-close-btn"]',
backLogo: '[data-cy="editor-page-logo"]',
backtoapps: '[data-cy="back-to-app-option"]',
signUpButton: '[data-cy="sign-up-button"]',
emailImage: '[data-cy="email-image"]',
spamMessage: '[data-cy="email-page-spam-msg"]',
resendEmailButton: '[data-cy="resend-email-button"]',
spamMessage: '[data-cy="info-message"]',
resendEmailButton: '[data-cy="resend-verification-email-button"]',
editEmailButton: '[data-cy="edit-email-button"]',
createAccountCheckMark: '[data-cy="create-account-check-mark"]',
createAccountCheckPoint: '[data-cy="create-account-check-point"]',
verifyEmailCheckMark: '[data-cy="verify-email-check-mark"]',
verifyEmailCheckPoint: '[data-cy="verify-email-check-point"]',
backtoSignUpButton: '[data-cy="back-to-signup-button"]',
forgotPasswordPageHeader: '[data-cy="forgot-password-page-header"]',
forgotPasswordPageSubHeader: '[data-cy="forgot-password-sub-header"]',
resetPasswordLinkButton: '[data-cy="reset-password-link"]',
forgotPasswordPageHeader: '[data-cy="forgot-password-header"]',
forgotPasswordPageSubHeader: '[data-cy="signup-redirect-text"]',
resetPasswordLinkButton: '[data-cy="send-a-reset-link-button"]',
enterIcon: '[data-cy="enter-icon"]',
passwordResetPageHeader: '[data-cy="reset-password-page-header"]',
passwordResetPageHeader: '[data-cy="reset-password-header"]',
newPasswordInputLabel: '[data-cy="new-password-input-label"]',
newPasswordInputField: '[data-cy="new-password-input-field"]',
newPasswordInputField: '[data-cy="new-password-input-input"]',
confirmPasswordInputFieldLabel: '[data-cy="confirm-password-input-label"]',
confirmPasswordInputField: '[data-cy="confirm-password-input-field"]',
confirmPasswordInputField: '[data-cy="confirm-password-input-input"]',
resetPasswordButton: '[data-cy="reset-password-button"]',
resetPasswordPageDescription: '[data-cy="reset-password-page-description"]',
backToLoginButton: '[data-cy="back-to-login-button"]',
backToLoginButton: '[data-cy="back-to-login"]',
breadcrumbTitle: '[data-cy="app-header-label"]>>',
breadcrumbPageTitle: '[data-cy="breadcrumb-page-title"]',
labelFullNameInput: '[data-cy="label-full-name-input-field"]',
inputFieldFullName: '[data-cy="input-field-full-name"]',
labelEmailInput: '[data-cy="label-email-input-field"]',
inputFieldEmailAddress: '[data-cy="input-field-email"]',
labelFullNameInput: '[data-cy="name-label"]',
inputFieldFullName: '[data-cy="name-input"]',
labelEmailInput: '[data-cy="email-label"]',
inputFieldEmailAddress: '[data-cy="email-input"]',
closeButton: '[data-cy="close-button"]',
emptyAppCreateButton: "[data-cy='button-new-app-from-scratch']",
globalDataSourceIcon: '[data-cy="icon-global-datasources"]',
@ -212,7 +222,7 @@ export const commonSelectors = {
return `[data-cy="${cyParamName(folderName)}-edit-folder-option"]`;
},
inspectorPinIcon: '.d-flex > [data-cy="left-sidebar-inspector"]',
groupInputFieldLabel: '[data-cy="label-group-input-field"]',
groupInputFieldLabel: '[data-cy="user-group-label"]',
pageSectionHeader: '[data-cy="dashboard-section-header"]',
yesButton: '[data-cy="yes-button"]',

View file

@ -16,7 +16,7 @@ export const dashboardSelector = {
ManageSSO: "[data-cy=manage-sso]",
userMenu: "[data-cy=user-menu]",
profileLink: "[data-cy=profile-link]",
logoutLink: "[data-cy=logout-link]",
logoutLink: '[data-cy="logout-link"]',
changeIconTitle: "[data-cy=change-icon-title]",
appCardDefaultIcon: "[data-cy=app-card-apps-icon]",
changeButton: "[data-cy=change-button]",

View file

@ -33,7 +33,7 @@ export const ssoSelector = {
redirectUrl: "[data-cy=redirect-url]",
googleTile: '[data-cy="google-sign-in-text"]',
googleIcon: "[data-cy=google-sso-icon]",
googleSSOText: "[data-cy=google-sso-text]",
googleSSOText: "[data-cy=google-sso-button-text]",
git: '[data-cy="github-sso-card"]',
gitEnableToggle: '[data-cy="github-toggle-input"]',
githubLabel: '[data-cy="github-label"]',
@ -43,7 +43,7 @@ export const ssoSelector = {
gitTile: "[data-cy=git-tile]",
gitIcon: "[data-cy=git-sso-icon]",
gitSignInText: "[data-cy=git-sso-text]",
gitSSOText: "[data-cy=git-sso-text]",
gitSSOText: "[data-cy=git-sso-button-text]",
password: "[data-cy=left-menu-items] :eq(3)",
passwordEnableToggle: '[data-cy="password-enable-toggle"]',
loginHelpText: "[data-cy=login-help-text]",

View file

@ -62,10 +62,7 @@ export const usersSelector = {
inputFieldBulkUpload: '[data-cy="input-field-bulk-upload"]',
copyInvitationLink: '[data-cy="copy-invitation-link"]',
uploadedFileData: '[data-cy="uploaded-file-data"]',
toastCloseButton:
'.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551 > [data-cy="toast-close-button"]',
toastCloseButton:'.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551 > [data-cy="toast-close-button"]',
userName: (userName) => {
return `[data-cy="${cyParamName(userName)}-user-name"]`;
},

View file

@ -0,0 +1,20 @@
export const cyParamName = (paramName = "") => {
return paramName.toLowerCase().replace(/\s+/g, "-");
};
export const onboardingSelectors = {
emailLabel: "[data-cy='email-label']",
emailInput: "[data-cy='email-input-input']",
signupEmailInput: "[data-cy='email-input']",
loginEmailInput: "[data-cy='email-input']",
passwordLabel: "[data-cy='password-label']",
passwordInput: "[data-cy='password-input-input']",
loginPasswordInput: "[data-cy='password-input']",
signInButton: "[data-cy='sign-in-button']",
passwordError: "[data-cy='password-error']",
nameInput: "[data-cy='name-input']",
nameLabel: '[data-cy="name-input-label"]',
signupNameLabel: '[data-cy="name-label"]',
forgotEmailInput: '[data-cy="email-input-field-input"]',
createAnAccountLink: '[data-cy="create-an-account-link"]',
}

View file

@ -52,13 +52,14 @@ export const commonText = {
},
closeButton: "modal close",
workEmailLabel: "Email",
emailInputError: "Invalid Email",
passwordLabel: "Password",
emailInputError: "Email is invalid",
passwordLabel: "Password *",
LoginPasswordLabel: "Password",
forgotPasswordLink: "Forgot?",
loginButton: " Login",
signInHeader: "Sign in",
signInSubHeader: "New to ToolJet?Create an account",
SignUpSectionHeader: "Join ToolJet",
signUpSectionHeader: "Join ToolJet",
signInRedirectText: "Already have an account?",
signInRedirectLink: "Sign in",
signUpTermsHelperText: "By signing up you are agreeing to the",
@ -67,11 +68,11 @@ export const commonText = {
invitePageHeader: "Join My workspace",
invitePageSubHeader:
"You are invited to a workspace My workspace. Accept the invite to join the workspace.",
userNameInputLabel: "Name",
acceptInviteButton: "Accept invite",
userNameInputLabel: "Name *",
acceptInviteButton: "Accept Invite",
createButton: "Create",
saveChangesButton: "Save changes",
emailInputLabel: "Email",
emailInputLabel: "Email *",
allApplicationLink: "All apps",
notificationsCardTitle: "Notifications",
emptyNotificationTitle: "You're all caught up!",
@ -86,7 +87,7 @@ export const commonText = {
"Lets set up your workspace to get started with ToolJet",
setUpToolJetButton: "Set up ToolJet",
setUpadminCheckPoint: "Set up admin",
setUpworkspaceCheckPoint: "Set up workspace",
setUpworkspaceCheckPoint: "Set up your workspace!",
companyProfileCheckPoint: "Company profile",
setUpAdminHeader: "Set up your admin account",
onboardingPageSubHeader: "This information will help us improve ToolJet.",
@ -94,17 +95,18 @@ export const commonText = {
continueButton: "Continue",
resetPasswordButton: "Reset password",
setUpWorkspaceHeader: "Set up your workspace",
loginPasswordLabel: "Password *",
userRolePageHeader: "What best describes your role?",
sizeOftheCompanyHeader: "What is the size of your company?",
workspaceNameInputLabel: "Workspace name",
workspaceNameInputLabel: "Workspace name *",
onboardingSeperatorText: "OR",
getStartedButton: "Get started for free",
emailPageHeader: "Check your mail",
spamMessage: "Did not receive an email? Check your spam folder.",
spamMessage: "Did not receive an email? Check your spam folder!",
resendEmailButton: "Resend verification mail",
editEmailButton: "Edit email address",
emailVerifiedText: "Successfully verified email",
continueToSetUp: "Continue to set up your workspace to start using ToolJet.",
continueToSetUp: "Set up workspaces to manage users, applications & resources across various teams",
createAccountCheckPoint: "Create account",
verifyEmailCheckPoint: "Verify email",
inalidInvitationLinkHeader: "Invalid verification link",
@ -114,15 +116,15 @@ export const commonText = {
forgotPasswordPageHeader: "Forgot Password",
newToTooljetText: "New to ToolJet?",
emailAddressLabel: "Email address",
resetPasswordLinkButton: " Send a reset link",
resetPasswordLinkButton: "Send a reset link",
passwordResetEmailToast:
"Please check your email/inbox for the password reset link",
"Please check your email for the password reset link",
passwordResetPageHeader: "Reset Password",
passwordResetSuccessPageHeader: "Password has been reset",
newPasswordInputLabel: "New Password",
confirmPasswordInputFieldLabel: "Re-enter the password",
newPasswordInputLabel: "New Password *",
confirmPasswordInputFieldLabel: "Re-enter the password *",
passwordResetSuccessToast: "Password reset successfully",
backToLoginButton: "Back to log in",
backToLoginButton: "Back to login",
resetPasswordPageDescription:
"Your password has been reset successfully, log into ToolJet to continue your session",
labelFullNameInput: "Enter full name",
@ -135,13 +137,13 @@ export const commonText = {
addNewDataSourceButton: "Add new datasource",
emailPageDescription: (email) => {
return `Weve sent an email to ${email} with a verification link. Please use that to verify your email address.`;
return `We've sent a verification email to ${email}. Click the link inside to confirm your email and continue. This helps us ensure account security.`
},
companyPageHeader: (userName) => {
return `Where do you work ${userName}?`;
},
resetPasswordEmailDescription: (email) => {
return `Weve sent an email to ${email} with a password reset link. Please click on that link to reset your password.`;
return `We've sent a password reset link to ${email}. Click the link inside to reset your password and continue.`;
},
userJobRole: {
HeadOfEngineering: "Head of engineering",

View file

@ -88,7 +88,7 @@ describe("App slug", () => {
);
cy.url().should(
"eq",
`http://localhost:8082/my-workspace/apps/${data.slug}/home`
`http://localhost:8082/my-workspace/apps/${data.slug}`
);
releaseApp();

View file

@ -14,6 +14,7 @@ import { addAppToGroup } from "Support/utils/manageGroups";
import { ssoSelector } from "Selectors/manageSSO";
import { fetchAndVisitInviteLink } from "Support/utils/manageUsers";
import { usersSelector } from "Selectors/manageUsers";
import { onboardingSelectors } from "Selectors/onboarding";
describe(
"App share functionality",
@ -26,7 +27,6 @@ describe(
const data = {};
beforeEach(() => {
cy.defaultWorkspaceLogin();
// cy.removeAssignedApps();
cy.skipWalkthrough();
});
@ -36,16 +36,19 @@ describe(
cy.apiCreateApp(data.appName);
cy.openApp();
cy.dragAndDropWidget("Table", 250, 250);
cy.addComponentToApp(data.appName, "text1");
verifyTooltip(
commonWidgetSelector.shareAppButton,
"Share URL is unavailable until current version is released"
);
cy.get('[data-cy="share-button-link"]>span').should(
"have.class",
"share-disabled"
);
//Need to automate with the new flow
// verifyTooltip(
// commonWidgetSelector.shareAppButton,
// "Share URL is unavailable until current version is released"
// );
// cy.get('[data-cy="share-button-link"]>span').should(
// "have.class",
// "share-disabled"
// );
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click();
@ -72,7 +75,7 @@ describe(
logout();
cy.wait(4000);
cy.get(commonSelectors.loginButton, { timeout: 20000 }).should(
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
cy.visitSlug({
@ -80,22 +83,22 @@ describe(
});
cy.wait(3000);
cy.get(commonSelectors.loginButton, { timeout: 20000 }).should(
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.loginButton).click();
cy.clearAndType(onboardingSelectors.emailInput, "dev@tooljet.io");
cy.clearAndType(onboardingSelectors.passwordInput, "password");
cy.get(onboardingSelectors.signInButton).click();
cy.wait(500);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(".text-widget-section > div").should("be.visible");
cy.get(commonSelectors.viewerPageLogo).click();
cy.openApp(
"my-workspace",
Cypress.env("appId"),
'[data-cy="draggable-widget-table1"]'
".text-widget-section > div"
);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).check();
@ -104,23 +107,22 @@ describe(
logout();
cy.wait(4000);
cy.get(commonSelectors.loginButton, { timeout: 20000 }).should(
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
cy.visitSlug({
actualUrl: `http://localhost:8082/applications/${data.slug}`,
});
cy.wait(3000);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(".text-widget-section > div").should("be.visible");
});
it("Verify app private and public app visibility for the same workspace user", () => {
data.appName = `${fake.companyName} App`;
data.slug = data.appName.toLowerCase().replace(/\s+/g, "-");
cy.apiCreateApp(data.appName);
cy.openApp();
cy.dragAndDropWidget("Table", 250, 250);
cy.addComponentToApp(data.appName, "text1");
releaseApp();
cy.wait(1000);
@ -132,13 +134,13 @@ describe(
cy.backToApps();
cy.visitSlug({ actualUrl: `/applications/${data.slug}` });
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(".text-widget-section > div").should("be.visible");
cy.defaultWorkspaceLogin();
cy.openApp(
"my-workspace",
Cypress.env("appId"),
'[data-cy="draggable-widget-table1"]'
".text-widget-section > div"
);
cy.wait(2000);
cy.get(commonWidgetSelector.shareAppButton).click();
@ -149,20 +151,21 @@ describe(
logout();
cy.wait(4000);
cy.get(commonSelectors.loginButton, { timeout: 20000 }).should(
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
cy.visitSlug({ actualUrl: `/applications/${data.slug}` });
cy.login("test@tooljet.com", "password");
cy.appUILogin("test@tooljet.com", "password");
cy.get(commonSelectors.allApplicationLink).verifyVisibleElement(
"have.text",
commonText.allApplicationLink
);
});
it("Verify app private and public app visibility for the same instance user", () => {
//Fix the case after bug fix
it.skip("Verify app private and public app visibility for the same instance user", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase();
data.appName = `${fake.companyName} App`;
@ -171,7 +174,8 @@ describe(
cy.apiCreateApp(data.appName);
cy.openApp();
cy.dragAndDropWidget("Table", 250, 250);
cy.addComponentToApp(data.appName, "text1");
releaseApp();
cy.wait(1000);
@ -183,13 +187,19 @@ describe(
cy.logoutApi();
userSignUp(data.firstName, data.email, data.workspaceName);
cy.wait(3000);
cy.backToApps();
cy.wait(1000);
cy.visitSlug({ actualUrl: `/applications/${data.slug}` });
cy.wait(1000);
cy.pause();
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.signInButton).click();
// logout();
cy.clearAndType(onboardingSelectors.emailInput, data.email);
cy.clearAndType(onboardingSelectors.passwordInput, "password");
cy.get(onboardingSelectors.signInButton).click();
cy.pause();
cy.wait(1000);
cy.get(ssoSelector.workspaceSubHeader).verifyVisibleElement(
"have.text",
@ -211,15 +221,16 @@ describe(
logout();
cy.wait(4000);
cy.get(commonSelectors.loginButton, { timeout: 20000 }).should(
cy.get(onboardingSelectors.signInButton, { timeout: 20000 }).should(
"be.visible"
);
cy.visitSlug({ actualUrl: `/applications/${data.slug}` });
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(".text-widget-section > div").should("be.visible");
cy.get(commonSelectors.viewerPageLogo).click();
});
it("hould redirect to the workspace login page, allow signup, proceed to accept invite page, and load the app", () => {
//Need to update with the new permission flow
it.skip("hould redirect to the workspace login page, allow signup, proceed to accept invite page, and load the app", () => {
let invitationToken,
organizationToken,
workspaceId,
@ -235,7 +246,8 @@ describe(
setSignupStatus(true);
cy.apiCreateApp(data.appName);
cy.openApp();
cy.dragAndDropWidget("Table", 250, 250);
cy.addComponentToApp(data.appName, "text1");
releaseApp();
cy.wait(1000);
@ -258,8 +270,8 @@ describe(
cy.get(commonSelectors.createAnAccountLink).click();
cy.clearAndType(commonSelectors.nameInputField, data.firstName);
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.clearAndType(onboardingSelectors.emailInput, data.email);
cy.clearAndType(onboardingSelectors.passwordInput, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.apiLogin();
@ -296,7 +308,7 @@ describe(
});
});
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(".text-widget-section > div").should("be.visible");
});
}
);

View file

@ -1,166 +0,0 @@
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
import * as signup from "Support/utils/selfHostSignUp";
import { logout } from "Support/utils/common";
describe("Self host onboarding", () => {
beforeEach(() => {
cy.visit('/setup');
});
it("verify elements on self host onboarding page", () => {
cy.get(commonSelectors.selfHostSetUpBanner).should("be.visible");
cy.get(commonSelectors.selfHostSetUpSubBanner).should("be.visible");
cy.get(commonSelectors.selfHostSetUpCard).should("be.visible");
cy.get(commonSelectors.selfHostSetUpCardImage).should("be.visible");
cy.get(commonSelectors.selfHostSetUpCardHeader).verifyVisibleElement(
"have.text",
commonText.selfHostSetUpCardHeader
);
cy.get(commonSelectors.selfHostSetUpCardSubHeader).verifyVisibleElement(
"have.text",
commonText.selfHostSetUpCardSubHeader
);
cy.get(commonSelectors.setUpToolJetButton)
.verifyVisibleElement("have.text", commonText.setUpToolJetButton)
.click();
signup.selfHostCommonElements();
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
commonText.setUpAdminHeader
);
cy.get(commonSelectors.userNameInputLabel).verifyVisibleElement(
"have.text",
commonText.userNameInputLabel
);
cy.get(commonSelectors.nameInputField).should("be.visible");
cy.get(commonSelectors.emailInputLabel).verifyVisibleElement(
"have.text",
commonText.emailInputLabel
);
cy.get(commonSelectors.emailInputField).should("be.visible");
cy.get(commonSelectors.passwordLabel).verifyVisibleElement(
"have.text",
commonText.passwordLabel
);
cy.get(commonSelectors.passwordInputField).should("be.visible");
cy.get(commonSelectors.passwordHelperText).verifyVisibleElement(
"have.text",
commonText.passwordHelperText
);
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
commonText.selfHostSignUpTermsHelperText
);
});
cy.get(commonSelectors.termsOfServiceLink)
.verifyVisibleElement("have.text", commonText.termsOfServiceLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/terms");
cy.get(commonSelectors.privacyPolicyLink)
.verifyVisibleElement("have.text", commonText.privacyPolicyLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/privacy");
cy.clearAndType(commonSelectors.nameInputField, "The Developer");
cy.clearAndType(commonSelectors.emailInputField, "dev@tooljet.io");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.continueButton).click();
signup.selfHostCommonElements();
cy.get(commonSelectors.userAccountNameAvatar).should("be.visible");
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
"Set up your workspace"
);
cy.get(commonSelectors.workspaceNameInputLabel).verifyVisibleElement(
"have.text",
commonText.workspaceNameInputLabel
);
cy.get(commonSelectors.workspaceNameInputField).should("be.visible");
cy.clearAndType(commonSelectors.workspaceNameInputField, "My workspace");
cy.get(commonSelectors.continueButton).click();
signup.selfHostCommonElements();
signup.commonElementsWorkspaceSetup();
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
commonText.companyPageHeader("The Developer")
);
cy.get(commonSelectors.companyNameInputField).should("be.visible");
cy.clearAndType(commonSelectors.companyNameInputField, "ToolJet");
cy.get(commonSelectors.continueButton).click();
signup.selfHostCommonElements();
signup.commonElementsWorkspaceSetup();
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
commonText.userRolePageHeader
);
signup.verifyandModifyUserRole();
signup.selfHostCommonElements();
signup.commonElementsWorkspaceSetup();
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
commonText.sizeOftheCompanyHeader
);
signup.verifyandModifySizeOftheCompany();
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.setUpadminCheckPoint).verifyVisibleElement(
"have.text",
commonText.setUpadminCheckPoint
);
cy.get(commonSelectors.setUpworkspaceCheckPoint).verifyVisibleElement(
"have.text",
commonText.setUpworkspaceCheckPoint
);
cy.get(commonSelectors.companyProfileCheckPoint).verifyVisibleElement(
"have.text",
commonText.companyProfileCheckPoint
);
cy.get(commonSelectors.onboardingPageSubHeader).verifyVisibleElement(
"have.text",
commonText.onboardingPageSubHeader
);
cy.get(commonSelectors.continueButton).verifyVisibleElement(
"have.text",
commonText.continueButton
);
signup.commonElementsWorkspaceSetup();
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
"Enter your phone number"
);
cy.get(".form-control").should("be.visible");
cy.get(".tj-onboarding-phone-input-wrapper")
.find("input")
.type("919876543210");
cy.get(commonSelectors.continueButton).click();
cy.get("body").then(($title) => {
if (!$title.text().includes("Enter your phone number")) {
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"
);
logout();
cy.appUILogin();
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"
);
}
});
});
});

View file

@ -1,183 +0,0 @@
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
import { fake } from "Fixtures/fake";
import { addNewUser } from "Support/utils/onboarding";
import { logout } from "Support/utils/common";
describe("Password reset functionality", () => {
const data = {};
let passwordResetLink = "";
it("Verify wrong password limit", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase();
cy.defaultWorkspaceLogin();
addNewUser(data.firstName, data.email);
logout();
for (let i = 0; i < 5; i++) {
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "passw");
cy.get(commonSelectors.loginButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Invalid credentials"
);
}
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "passw");
cy.get(commonSelectors.loginButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Maximum password retry limit reached, please reset your password using forgot password option"
);
});
it("Verify forgot password page elements and functionality", () => {
cy.visit("/");
cy.get(commonSelectors.forgotPasswordLink).click();
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.forgotPasswordPageHeader).verifyVisibleElement(
"have.text",
commonText.forgotPasswordPageHeader
);
cy.get(commonSelectors.forgotPasswordPageSubHeader).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
"New to"
);
});
cy.get(commonSelectors.createAnAccountLink).verifyVisibleElement(
"have.text",
commonText.createAnAccountLink
);
cy.get(commonSelectors.emailInputLabel).verifyVisibleElement(
"have.text",
commonText.emailAddressLabel
);
cy.get(commonSelectors.emailInputField).should("be.visible");
cy.get(commonSelectors.resetPasswordLinkButton)
.verifyVisibleElement("have.text", commonText.resetPasswordLinkButton)
.and("be.disabled");
cy.get(commonSelectors.enterIcon).should("be.visible");
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.get(commonSelectors.resetPasswordLinkButton).click();
cy.get("body").then(($title) => {
if (!$title.text().includes("Forgot Password")) {
cy.verifyToastMessage(
commonSelectors.toastMessage,
commonText.passwordResetEmailToast
);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.emailImage).should("be.visible");
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
commonText.emailPageHeader
);
cy.get(commonSelectors.onboardingPageDescription).verifyVisibleElement(
"have.text",
commonText.resetPasswordEmailDescription(data.email)
);
cy.get(commonSelectors.spamMessage).verifyVisibleElement(
"have.text",
commonText.spamMessage
);
cy.get(commonSelectors.onboardingSeperator).should("be.visible");
cy.get(commonSelectors.onboardingSeperatorText).verifyVisibleElement(
"have.text",
commonText.onboardingSeperatorText
);
cy.get(commonSelectors.backToLoginButton).verifyVisibleElement(
"have.text",
commonText.backToLoginButton
);
}
});
cy.task("updateId", {
dbconfig: Cypress.env("app_db"),
sql: `select forgot_password_token from users where email='${data.email}';`,
}).then((resp) => {
passwordResetLink = `/reset-password/${resp.rows[0].forgot_password_token}`;
});
});
it("Verify reset password page and functionality", () => {
cy.visit(passwordResetLink);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.passwordResetPageHeader).verifyVisibleElement(
"have.text",
commonText.passwordResetPageHeader
);
cy.get(commonSelectors.newPasswordInputLabel).verifyVisibleElement(
"have.text",
commonText.newPasswordInputLabel
);
cy.get(commonSelectors.newPasswordInputField).should("be.visible");
cy.get(commonSelectors.passwordHelperText)
.eq(0)
.verifyVisibleElement("have.text", commonText.passwordHelperText);
cy.get(commonSelectors.confirmPasswordInputFieldLabel).verifyVisibleElement(
"have.text",
commonText.confirmPasswordInputFieldLabel
);
cy.get(commonSelectors.confirmPasswordInputField).should("be.visible");
cy.get(commonSelectors.passwordHelperText)
.eq(1)
.verifyVisibleElement("have.text", commonText.passwordHelperText);
cy.get(commonSelectors.resetPasswordButton)
.verifyVisibleElement("have.text", commonText.resetPasswordButton)
.and("be.disabled");
cy.get(commonSelectors.enterIcon).should("be.visible");
cy.clearAndType(commonSelectors.newPasswordInputField, "Pass");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.get(commonSelectors.newPasswordInputField).clear();
cy.clearAndType(commonSelectors.confirmPasswordInputField, "Pass");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.clearAndType(commonSelectors.newPasswordInputField, "Pass");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "Pass");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.clearAndType(commonSelectors.newPasswordInputField, "password1");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "password");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.clearAndType(commonSelectors.newPasswordInputField, "Password");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "password");
cy.get(commonSelectors.resetPasswordButton).click();
cy.verifyToastMessage(commonSelectors.toastMessage, "Password don't match");
cy.clearAndType(commonSelectors.newPasswordInputField, "Password");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "Password");
cy.get(commonSelectors.resetPasswordButton).should("be.enabled").click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
commonText.passwordResetSuccessToast
);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.passwordResetPageHeader).verifyVisibleElement(
"have.text",
commonText.passwordResetSuccessPageHeader
);
cy.get(commonSelectors.resetPasswordPageDescription).verifyVisibleElement(
"have.text",
commonText.resetPasswordPageDescription
);
cy.get(commonSelectors.backToLoginButton).verifyVisibleElement(
"have.text",
commonText.backToLoginButton
);
});
it("Verify user login using new password", () => {
cy.visit("/");
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "Password");
cy.get(commonSelectors.loginButton).click();
cy.get(commonSelectors.workspaceName).should("be.visible");
});
});

View file

@ -1,85 +0,0 @@
import { commonSelectors } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { commonText, path } from "Texts/common";
describe("Login functionality", () => {
let user;
const invalidEmail = fake.email;
const invalidPassword = fake.password;
beforeEach(() => {
cy.fixture("credentials/login.json").then((login) => {
user = login;
});
cy.visit("/");
});
it("Should verify elements on the login page", () => {
cy.url().should("include", path.loginPath);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.signInHeader).verifyVisibleElement(
"have.text",
commonText.signInHeader
);
cy.get(commonSelectors.workEmailLabel).verifyVisibleElement(
"have.text",
commonText.workEmailLabel
);
cy.get(commonSelectors.passwordLabel).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
commonText.passwordLabel
);
});
cy.get(commonSelectors.forgotPasswordLink).verifyVisibleElement(
"have.text",
commonText.forgotPasswordLink
);
cy.get(commonSelectors.loginButton).verifyVisibleElement(
"have.text",
commonText.loginButton
);
cy.get(commonSelectors.workEmailInputField).should("be.visible");
cy.get(commonSelectors.passwordInputField).should("be.visible");
});
it("Should not be able to login with invalid credentials", () => {
cy.get(commonSelectors.loginButton).click();
cy.get(commonSelectors.emailInputError).verifyVisibleElement(
"have.text",
commonText.emailInputError
);
cy.clearAndType(commonSelectors.workEmailInputField, invalidEmail);
cy.get(commonSelectors.loginButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
commonText.loginErrorToast
);
cy.get(commonSelectors.workEmailInputField).clear();
cy.clearAndType(commonSelectors.passwordInputField, invalidPassword);
cy.get(commonSelectors.loginButton).click();
cy.get(commonSelectors.emailInputError).verifyVisibleElement(
"have.text",
commonText.emailInputError
);
cy.clearAndType(commonSelectors.workEmailInputField, user.email);
cy.get(commonSelectors.passwordInputField).clear();
cy.get(commonSelectors.loginButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
commonText.loginErrorToast
);
cy.get(commonSelectors.workEmailInputField).clear();
cy.clearAndType(commonSelectors.passwordInputField, user.password);
cy.get(commonSelectors.loginButton).click();
cy.get(commonSelectors.emailInputError).verifyVisibleElement(
"have.text",
commonText.emailInputError
);
});
it("Should be able to login with valid credentials", () => {
cy.login(user.email, user.password);
});
});

View file

@ -1,104 +0,0 @@
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
import { SignUpPageElements } from "Support/utils/onboarding";
import { fake } from "Fixtures/fake";
import {
verifyConfirmEmailPage,
verifyConfirmPageElements,
verifyOnboardingQuestions,
verifyInvalidInvitationLink,
updateWorkspaceName
} from "Support/utils/onboarding";
import { dashboardText } from "Texts/dashboard";
import {
verifyandModifyUserRole,
verifyandModifySizeOftheCompany,
} from "Support/utils/selfHostSignUp";
describe("User signup", () => {
const data = {};
let invitationLink = "";
it("Verify the signup flow and UI elements", () => {
data.fullName = fake.fullName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.workspaceName = fake.companyName;
cy.visit("/");
cy.get(commonSelectors.createAnAccountLink).realClick();
SignUpPageElements();
cy.clearAndType(commonSelectors.nameInputField, data.fullName);
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.wait(500);
verifyConfirmEmailPage(data.email);
cy.task("updateId", {
dbconfig: Cypress.env("app_db"),
sql: `select invitation_token from users where email='${data.email}';`,
}).then((resp) => {
invitationLink = `/invitations/${resp.rows[0].invitation_token}`;
cy.visit(invitationLink);
});
verifyConfirmPageElements();
cy.get(commonSelectors.setUpToolJetButton).click();
cy.wait(4000);
verifyOnboardingQuestions(data.fullName, data.workspaceName);
});
it("Verify invalid invitation link", () => {
cy.log(invitationLink)
cy.visit(invitationLink);
verifyInvalidInvitationLink();
cy.get(commonSelectors.backtoSignUpButton).click();
cy.get(commonSelectors.SignUpSectionHeader).should("be.visible");
});
it("Verify onboarding flow", () => {
data.fullName = fake.fullName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.workspaceName = fake.companyName;
cy.visit("/");
cy.get(commonSelectors.createAnAccountLink).realClick();
cy.clearAndType(commonSelectors.nameInputField, data.fullName);
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.wait(8000);
cy.get(commonSelectors.resendEmailButton).click();
cy.get(commonSelectors.editEmailButton).click();
cy.get(commonSelectors.nameInputField).verifyVisibleElement("have.value", data.fullName)
cy.get(commonSelectors.emailInputField).verifyVisibleElement("have.value", data.email);
cy.get(commonSelectors.passwordInputField).verifyVisibleElement("have.value", "");
cy.task("updateId", {
dbconfig: Cypress.env("app_db"),
sql: `select invitation_token from users where email='${data.email}';`,
}).then((resp) => {
invitationLink = `/invitations/${resp.rows[0].invitation_token}`;
cy.visit(invitationLink);
});
cy.get(commonSelectors.setUpToolJetButton).click();
cy.clearAndType(commonSelectors.companyNameInputField, data.workspaceName);
cy.get(commonSelectors.continueButton).focus().type('{enter}');
cy.get(commonSelectors.backArrow).click()
cy.get(commonSelectors.companyNameInputField).verifyVisibleElement("have.value", data.workspaceName);
cy.get(commonSelectors.continueButton).focus().type('{enter}');
cy.get('[data-cy="head-of-engineering-radio-button"]').check()
cy.get(commonSelectors.continueButton).focus().type('{enter}');
cy.get(commonSelectors.backArrow).click()
cy.get('[data-cy="head-of-engineering-radio-button"]').should("be.checked")
cy.get(commonSelectors.continueButton).focus().type('{enter}');
cy.get('[data-cy="1-10-radio-button"]').check()
cy.get(commonSelectors.continueButton).focus().type('{enter}');
cy.get(commonSelectors.backArrow).click()
cy.get('[data-cy="1-10-radio-button"]').should("be.checked")
cy.get(commonSelectors.continueButton).focus().type('{enter}');
})
});

View file

@ -0,0 +1,88 @@
import { commonSelectors } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { commonText, path } from "Texts/common";
import { onboardingSelectors } from "Selectors/onboarding";
import { dashboardSelector } from "Selectors/dashboard";
import { logout } from "Support/utils/common";
describe("Login functionality", () => {
let user;
const invalidEmail = fake.email;
const invalidPassword = fake.password;
beforeEach(() => {
cy.fixture("credentials/login.json").then((login) => {
user = login;
});
cy.visit("/");
});
it("Should verify elements on the login page", () => {
cy.url().should("include", path.loginPath);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.signInHeader).verifyVisibleElement(
"have.text",
commonText.signInHeader
);
cy.get(onboardingSelectors.emailLabel).verifyVisibleElement(
"have.text",
"Email *"
);
cy.get(onboardingSelectors.passwordLabel).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
commonText.LoginPasswordLabel
);
});
cy.get(commonSelectors.forgotPasswordLink).verifyVisibleElement(
"have.text",
commonText.forgotPasswordLink
);
cy.get(onboardingSelectors.signInButton).verifyVisibleElement(
"have.text",
"Sign in"
);
cy.get(onboardingSelectors.signInButton).should("be.disabled");
cy.get(onboardingSelectors.signupEmailInput).should("be.visible");
cy.get(onboardingSelectors.loginPasswordInput).should("be.visible");
});
it("Should be able to login with valid credentials", () => {
cy.appUILogin(user.email, user.password);
cy.get(commonSelectors.settingsIcon).click();
cy.get(dashboardSelector.logoutLink);
});
it("Should not be able to login with invalid credentials", () => {
cy.wait(3000);
cy.clearAndType(onboardingSelectors.signupEmailInput, "test");
cy.clearAndType(onboardingSelectors.signupEmailInput, "test");
cy.get(commonSelectors.emailInputError).verifyVisibleElement(
"have.text",
commonText.emailInputError
);
cy.get(onboardingSelectors.signInButton).should("be.disabled");
cy.get(onboardingSelectors.signupEmailInput).clear();
cy.clearAndType(onboardingSelectors.loginPasswordInput, invalidPassword);
cy.get(onboardingSelectors.signInButton).should("be.disabled");
cy.clearAndType(onboardingSelectors.signupEmailInput, user.email);
cy.get(onboardingSelectors.loginPasswordInput).clear();
cy.get(onboardingSelectors.signInButton).should("be.disabled");
cy.clearAndType(onboardingSelectors.signupEmailInput, user.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "Pass");
cy.get(onboardingSelectors.passwordError).verifyVisibleElement(
"have.text",
"Password must be at least 5 characters long"
);
cy.clearAndType(onboardingSelectors.loginPasswordInput, invalidPassword);
cy.get(onboardingSelectors.signInButton).click();
cy.verifyToastMessage(commonSelectors.toastMessage, "Invalid credentials");
});
it("Should be able to login with valid credentials using api", () => {
cy.appUILogin(user.email, user.password);
logout();
});
});

View file

@ -0,0 +1,90 @@
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
import { SignUpPageElements } from "Support/utils/onboarding";
import { fake } from "Fixtures/fake";
import {
verifyConfirmEmailPage,
verifyConfirmPageElements,
verifyOnboardingQuestions,
verifyInvalidInvitationLink,
updateWorkspaceName,
} from "Support/utils/onboarding";
import { dashboardText } from "Texts/dashboard";
import {
verifyandModifyUserRole,
verifyandModifySizeOftheCompany,
} from "Support/utils/selfHostSignUp";
import { onboardingSelectors } from "Selectors/onboarding";
import { logout } from "Support/utils/common";
describe("User signup", () => {
const data = {};
let invitationLink = "";
it("Verify the signup flow and UI elements", () => {
data.fullName = fake.fullName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.workspaceName = fake.companyName;
cy.visit("/");
cy.get(commonSelectors.createAnAccountLink).realClick();
SignUpPageElements();
cy.get(onboardingSelectors.nameInput).clear();
cy.get(onboardingSelectors.nameInput).type(data.fullName);
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(
onboardingSelectors.loginPasswordInput,
commonText.password
);
cy.get(commonSelectors.signUpButton).click();
cy.wait(500);
verifyConfirmEmailPage(data.email);
cy.task("updateId", {
dbconfig: Cypress.env("app_db"),
sql: `select invitation_token from users where email='${data.email}';`,
}).then((resp) => {
invitationLink = `/invitations/${resp.rows[0].invitation_token}`;
cy.visit(invitationLink);
});
logout();
});
it("Verify invalid invitation link", () => {
cy.log(invitationLink);
cy.visit(invitationLink);
verifyInvalidInvitationLink();
cy.get(commonSelectors.pageLogo).click();
cy.get('[data-cy="sign-in-header"]').should("be.visible");
});
it("Verify onboarding flow", () => {
// rewrite for for EE and cloud
data.fullName = fake.fullName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.workspaceName = fake.companyName;
cy.visit("/");
cy.wait(8000);
cy.get(onboardingSelectors.createAnAccountLink).click();
cy.wait(6000);
cy.get(onboardingSelectors.nameInput).clear();
cy.get(onboardingSelectors.nameInput).type(data.fullName);
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(
onboardingSelectors.loginPasswordInput,
commonText.password
);
cy.get(commonSelectors.signUpButton).click();
cy.wait(8000);
cy.get(commonSelectors.resendEmailButton).click();
cy.task("updateId", {
dbconfig: Cypress.env("app_db"),
sql: `select invitation_token from users where email='${data.email}';`,
}).then((resp) => {
invitationLink = `/invitations/${resp.rows[0].invitation_token}`;
});
});
});

View file

@ -11,6 +11,21 @@ import {
inviteUserWithUserRole,
fetchAndVisitInviteLink,
} from "Support/utils/manageUsers";
import {
addNewUser,
visitWorkspaceInvitation,
newInvite,
} from "Support/utils/onboarding";
import { commonText } from "Texts/common";
import { setSignupStatus, enableSignUp } from "Support/utils/manageSSO";
import { ssoSelector } from "Selectors/manageSSO";
import {
SignUpPageElements,
verifyConfirmEmailPage,
signUpLink,
verifyOnboardingQuestions,
} from "Support/utils/onboarding";
import {
navigateToManageUsers,
logout,
@ -20,20 +35,20 @@ import {
import { updateWorkspaceName } from "Support/utils/userPermissions";
import { groupsSelector } from "Selectors/manageGroups";
import { groupsText } from "Texts/manageGroups";
import { addNewUser, visitWorkspaceInvitation } from "Support/utils/onboarding";
import { commonText } from "Texts/common";
import { onboardingSelectors } from "Selectors/onboarding";
let invitationToken,
organizationToken,
workspaceId,
userId,
url = "";
const data = {};
describe("Manage Users", () => {
describe("user invite flow cases", () => {
beforeEach(() => {
cy.defaultWorkspaceLogin();
});
let invitationToken,
organizationToken,
workspaceId,
userId,
url = "";
it("Should verify the Manage users page", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
@ -45,8 +60,7 @@ describe("Manage Users", () => {
cy.get(usersSelector.usersPageTitle).should("be.visible");
cy.get(usersSelector.buttonAddUsers).click();
cy.get(usersSelector.buttonInviteUsers).should('be.disabled');
cy.get(usersSelector.buttonInviteUsers).should("be.disabled");
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
cy.clearAndType(commonSelectors.inputFieldEmailAddress, data.email);
@ -55,7 +69,7 @@ describe("Manage Users", () => {
"have.text",
"Email is not valid"
);
cy.get(usersSelector.buttonInviteUsers).should('be.disabled');
cy.get(usersSelector.buttonInviteUsers).should("be.disabled");
cy.clearAndType(commonSelectors.inputFieldFullName, data.firstName);
cy.clearAndType(
@ -64,18 +78,25 @@ describe("Manage Users", () => {
);
cy.get(usersSelector.buttonInviteUsers).click();
cy.get('[data-cy="modal-icon"]').should('be.visible')
cy.get('[data-cy="modal-header"]').verifyVisibleElement("have.text", "Duplicate email");
cy.get(commonSelectors.modalMessage).verifyVisibleElement("have.text", "Duplicate email found. Please provide a unique email address.")
cy.get('[data-cy="close-button"]:eq(1)').should('be.visible').click();
cy.get(commonSelectors.inputFieldEmailAddress).should("have.value", usersText.adminUserEmail)
cy.get('[data-cy="modal-icon"]').should("be.visible");
cy.get('[data-cy="modal-header"]').verifyVisibleElement(
"have.text",
"Duplicate email"
);
cy.get(commonSelectors.modalMessage).verifyVisibleElement(
"have.text",
"Duplicate email found. Please provide a unique email address."
);
cy.get('[data-cy="close-button"]:eq(1)').should("be.visible").click();
cy.get(commonSelectors.inputFieldEmailAddress).should(
"have.value",
usersText.adminUserEmail
);
});
it("Should verify the confirm invite page and new user account", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
// cy.removeAssignedApps();
navigateToManageUsers();
fillUserInviteForm(data.firstName, data.email);
@ -84,9 +105,9 @@ describe("Manage Users", () => {
fetchAndVisitInviteLink(data.email);
confirmInviteElements(data.email);
cy.clearAndType(commonSelectors.passwordInputField, "pass");
cy.clearAndType(onboardingSelectors.loginPasswordInput, "pass");
cy.get(commonSelectors.signUpButton).should("be.disabled");
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
cy.clearAndType(onboardingSelectors.loginPasswordInput, usersText.password);
cy.get(commonSelectors.signUpButton).should("not.be.disabled");
cy.get(commonSelectors.signUpButton).click();
@ -98,14 +119,12 @@ describe("Manage Users", () => {
"have.text",
commonText.invitePageSubHeader
);
cy.verifyLabel("Name");
cy.get(commonSelectors.invitedUserName).verifyVisibleElement(
"have.text",
data.firstName
);
cy.verifyLabel("Email");
cy.get(commonSelectors.invitedUserEmail).verifyVisibleElement(
cy.wait(3000);
cy.get(commonSelectors.invitedUseremail).verifyVisibleElement(
"have.text",
data.email
);
@ -155,14 +174,9 @@ describe("Manage Users", () => {
logout();
cy.visit("/");
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
cy.get(commonSelectors.loginButton).click();
updateWorkspaceName(data.email);
cy.get(commonSelectors.workspaceName).click();
cy.contains("My workspace").should("not.exist");
logout();
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, usersText.password);
cy.get(onboardingSelectors.signInButton).click();
cy.defaultWorkspaceLogin();
navigateToManageUsers();
@ -177,9 +191,9 @@ describe("Manage Users", () => {
visitWorkspaceInvitation(data.email, "My workspace");
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.signInButton).click();
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
cy.get(onboardingSelectors.signInButton).click();
cy.get(usersSelector.acceptInvite).click();
cy.verifyToastMessage(commonSelectors.toastMessage, usersText.inviteToast);
logout();
@ -199,7 +213,6 @@ describe("Manage Users", () => {
data.groupName1 = fake.firstName.replaceAll("[^A-Za-z]", "");
data.groupName2 = fake.firstName.replaceAll("[^A-Za-z]", "");
const groupNames = ["All users", "Admin"];
navigateToManageUsers();
@ -213,10 +226,6 @@ describe("Manage Users", () => {
}
});
cy.get('[data-cy="user-group-select"]>>>>>').eq(0).type("Test");
cy.get(".css-1wlit7h-NoOptionsMessage").verifyVisibleElement(
"have.text",
"No groups found"
);
cy.get(commonSelectors.cancelButton).click();
cy.get(usersSelector.buttonAddUsers).click();
@ -225,7 +234,7 @@ describe("Manage Users", () => {
cy.get(commonSelectors.cancelButton).click();
cy.get(usersSelector.buttonAddUsers).click();
cy.get('.selected-value').should('have.text', "End-user")
cy.get(".selected-value").should("have.text", "End-user");
cy.get(commonSelectors.cancelButton).click();
inviteUserWithUserRole(data.firstName, data.email, "Admin");
@ -257,7 +266,7 @@ describe("Manage Users", () => {
data.groupName2
);
logout();
cy.wait(3000);
cy.defaultWorkspaceLogin();
navigateToManageGroups();
cy.get(groupsSelector.groupLink(data.groupName1)).click();
@ -337,12 +346,27 @@ describe("Manage Users", () => {
cy.get(usersSelector.buttonInviteUsers).click();
cy.get('[data-cy="modal-title"] > .tj-text-md').verifyVisibleElement("have.text", "Edit user role")
cy.get('[data-cy="user-email"]').verifyVisibleElement("have.text", data.email);
cy.get('[data-cy="modal-body"]>').verifyVisibleElement("have.text", "Are you sure you want to continue?");
cy.get('.modal-footer > [data-cy="cancel-button"]').verifyVisibleElement("have.text", "Cancel");
cy.get('[data-cy="confim-button"]').verifyVisibleElement("have.text", "Continue");
cy.get('[data-cy="modal-close-button"]').should('be.visible').click();
cy.get('[data-cy="modal-title"] > .tj-text-md').verifyVisibleElement(
"have.text",
"Edit user role"
);
cy.get('[data-cy="user-email"]').verifyVisibleElement(
"have.text",
data.email
);
cy.get('[data-cy="modal-body"]>').verifyVisibleElement(
"have.text",
"Updating the user's details will change their role from end-user to admin. Are you sure you want to continue?"
);
cy.get('.modal-footer > [data-cy="cancel-button"]').verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get('[data-cy="confim-button"]').verifyVisibleElement(
"have.text",
"Continue"
);
cy.get('[data-cy="modal-close-button"]').should("be.visible").click();
cy.get(usersSelector.userActionButton).click();
cy.get(usersSelector.editUserDetailsButton).click();
@ -359,7 +383,7 @@ describe("Manage Users", () => {
cy.get('[data-cy="group-check-input"]').eq(0).check();
cy.get(usersSelector.buttonInviteUsers).click();
cy.get('.modal-footer > [data-cy="cancel-button"]').click()
cy.get('.modal-footer > [data-cy="cancel-button"]').click();
cy.get(usersSelector.userActionButton).click();
cy.get(usersSelector.editUserDetailsButton).click();
@ -376,7 +400,7 @@ describe("Manage Users", () => {
cy.get('[data-cy="group-check-input"]').eq(0).check();
cy.get(usersSelector.buttonInviteUsers).click();
cy.get('[data-cy="confim-button"]').click()
cy.get('[data-cy="confim-button"]').click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
@ -384,7 +408,10 @@ describe("Manage Users", () => {
);
searchUser(data.email);
cy.get('[data-name="role-header"] [data-cy="group-chip"]').should("have.text", "Admin");
cy.get('[data-name="role-header"] [data-cy="group-chip"]').should(
"have.text",
"Admin"
);
});
it("Should verify exisiting user invite flow", () => {
@ -404,10 +431,10 @@ describe("Manage Users", () => {
cy.get(usersSelector.buttonInviteUsers).click();
cy.wait(2000);
visitWorkspaceInvitation(data.email, workspaceName);
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.signInButton).click();
cy.wait(3000);
cy.clearAndType(onboardingSelectors.loginEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
cy.get(onboardingSelectors.signInButton).click();
cy.get(usersSelector.acceptInvite).click();
cy.verifyToastMessage(commonSelectors.toastMessage, usersText.inviteToast);
logout();
@ -421,4 +448,118 @@ describe("Manage Users", () => {
cy.get("td small").should("have.text", usersText.activeStatus);
});
});
it("should verify the user signup after invited in a workspace", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.signUpName = fake.firstName;
data.workspaceName = fake.companyName;
setSignupStatus(true);
navigateToManageUsers();
fillUserInviteForm(data.firstName, data.email);
cy.get(usersSelector.buttonInviteUsers).click();
cy.logoutApi();
cy.visit("/");
cy.get(commonSelectors.createAnAccountLink).click();
SignUpPageElements();
cy.wait(3000);
cy.clearAndType(onboardingSelectors.nameInput, data.signUpName);
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(
onboardingSelectors.loginPasswordInput,
commonText.password
);
cy.get(commonSelectors.signUpButton).click();
cy.wait(1000);
signUpLink(data.email);
cy.wait(1000);
visitWorkspaceInvitation(data.email, "My workspace");
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, usersText.password);
cy.get(onboardingSelectors.signInButton).click();
cy.wait(3000);
cy.get(commonSelectors.invitedUserName).verifyVisibleElement(
"have.text",
data.signUpName
);
cy.get(commonSelectors.acceptInviteButton).click();
});
it("should verify the user signup with same creds after invited in a workspace", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.signUpName = fake.firstName;
data.workspaceName = fake.companyName;
setSignupStatus(true);
navigateToManageUsers();
fillUserInviteForm(data.firstName, data.email);
cy.get(usersSelector.buttonInviteUsers).click();
logout();
cy.get(commonSelectors.createAnAccountLink).click();
SignUpPageElements();
cy.wait(5000);
cy.clearAndType(onboardingSelectors.nameInput, data.signUpName);
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(
onboardingSelectors.loginPasswordInput,
commonText.password
);
cy.get(commonSelectors.signUpButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"The user is already registered. Please check your inbox for the activation link"
);
});
it("should verify exisiting user workspace signup from instance using form", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.signUpName = fake.firstName;
data.workspaceName = fake.firstName.toLowerCase();
setSignupStatus(true);
navigateToManageUsers();
addNewUser(data.firstName, data.email);
logout();
cy.wait(3000);
cy.get(commonSelectors.createAnAccountLink).click();
cy.wait(1000);
cy.clearAndType(onboardingSelectors.nameInput, data.firstName);
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(
onboardingSelectors.loginPasswordInput,
commonText.password
);
cy.get(commonSelectors.signUpButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"User already exists in the workspace."
);
cy.apiLogin();
cy.apiCreateWorkspace(data.workspaceName, data.workspaceName);
cy.visit(`${data.workspaceName}`);
cy.wait(3000);
setSignupStatus(true, data.workspaceName);
logout();
cy.get(commonSelectors.createAnAccountLink).click();
cy.wait(3000);
cy.clearAndType(onboardingSelectors.nameInput, data.firstName);
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(
onboardingSelectors.loginPasswordInput,
commonText.password
);
cy.get(commonSelectors.signUpButton).click();
cy.defaultWorkspaceLogin();
visitWorkspaceInvitation(data.email, data.workspaceName);
cy.verifyToastMessage(commonSelectors.toastMessage, usersText.inviteToast);
logout();
});
});

View file

@ -29,6 +29,7 @@ describe("Bulk user upload", () => {
const without_lastName =
"cypress/fixtures/bulkUser/without_lastname - Sheet1.csv";
const invite_users = "cypress/fixtures/bulkUser/invite_users - Sheet1 .csv";
const Validinvite = "cypress/fixtures/bulkUser/10usersupload.csv";
it("Verfiy bulk user upload invalid files", () => {
data.firstName = fake.firstName;
@ -42,80 +43,86 @@ describe("Bulk user upload", () => {
cy.get(usersSelector.buttonAddUsers).click();
cy.get(usersSelector.buttonUploadCsvFile).click();
bulkUserUpload(
without_name,
"without_name",
"Invalid row(s): [first_name, last_name] in [11] row(s). No users were uploaded."
"Missing first_name,last_name,groups information in 10 row(s);. No users were uploaded, please update and try again."
);
bulkUserUpload(
without_email,
"without_email",
"Invalid row(s): [email] in [11] row(s). No users were uploaded."
);
bulkUserUpload(
without_group,
"without_group",
"Invalid row(s): [groups] in [5] row(s). No users were uploaded."
);
bulkUserUpload(
same_email,
"same_email",
"Duplicate email found. Please provide a unique email address."
);
bulkUserUpload(
invalid_group_name,
"invalid_group_name",
"11 groups doesn't exist. No users were uploaded"
"Missing email,groups information in 10 row(s);. No users were uploaded, please update and try again."
);
// bulkUserUpload(
// without_group,
// "without_group",
// "Invalid row(s): [groups] in [5] row(s). No users were uploaded."
// );
//Add automation for modal data-cy="close-button"
// bulkUserUpload(
// same_email,
// "same_email",
// "Duplicate email found. Please provide a unique email address."
// );
// bulkUserUpload(
// invalid_group_name,
// "invalid_group_name",
// "11 groups doesn't exist. No users were uploaded"
// );
bulkUserUpload(
empty_first_and_last_name,
"empty_first_and_last_name",
"Invalid row(s): [first_name, last_name] in [1] row(s). No users were uploaded."
"Missing first_name,last_name,groups information in 1 row(s);. No users were uploaded, please update and try again."
);
bulkUserUpload(
limit_exceeded_list,
"500_invite_users",
"You can only invite 250 users at a time"
);
bulkUserUpload(
non_existing_group,
"non_existing_group",
"1 group doesn't exist. No users were uploaded"
);
bulkUserUpload(
multiple_groups,
"multiple_groups",
"Conflicting Group Memberships: User cannot be in both the Admin group and other groups simultaneously."
"2 groups doesn't exist. No users were uploaded"
);
cy.get(usersSelector.inputFieldBulkUpload).selectFile(without_firstName, {
force: true,
});
cy.get(usersSelector.uploadedFileData).should(
"contain",
"without_firstname"
);
cy.get(usersSelector.buttonUploadUsers).click();
cy.get(".go2072408551")
.should("be.visible")
.and("have.text", "5 users are being added");
//add more groups and verify
cy.wait(5000);
// bulkUserUpload(
// multiple_groups,
// "multiple_groups",
// "Conflicting Group Memberships: User cannot be in both the Admin group and other groups simultaneously."
// );
cy.get(usersSelector.buttonAddUsers).click();
cy.get(usersSelector.buttonUploadCsvFile).click();
cy.get(usersSelector.inputFieldBulkUpload).selectFile(without_lastName, {
force: true,
});
cy.get(usersSelector.uploadedFileData).should(
"contain",
"without_lastname"
);
cy.get(usersSelector.buttonUploadUsers).click();
cy.get(".go2072408551")
.should("be.visible")
.and("have.text", "5 users are being added");
// cy.get(usersSelector.inputFieldBulkUpload).selectFile(without_firstName, {
// force: true,
// });
// cy.get(usersSelector.uploadedFileData).should(
// "contain",
// "without_firstname"
// );
// cy.get(usersSelector.buttonUploadUsers).click();
// cy.get(".go2072408551")
// .should("be.visible")
// .and("have.text", "Missing first_name,user_role,groups information in 5 row(s);. No users were uploaded, please update and try again.Missing first_name,user_role,groups information in 5 row(s);. No users were uploaded, please update and try again.");
// cy.wait(5000);
// // cy.get(usersSelector.buttonAddUsers).click();
// cy.get(usersSelector.buttonUploadCsvFile).click();
// cy.get(usersSelector.inputFieldBulkUpload).selectFile(without_lastName, {
// force: true,
// });
// cy.get(usersSelector.uploadedFileData).should(
// "contain",
// "without_lastname"
// );
// cy.get(usersSelector.buttonUploadUsers).click();
// cy.get(".go2072408551")
// .should("be.visible")
// .and("have.text", "Missing last_name,user_role,groups information in 5 row(s);. No users were uploaded, please update and try again.Missing last_name,user_role,groups information in 5 row(s);. No users were uploaded, please update and try again.");
});
it("Verify bulk user upload functionality", () => {
@ -130,22 +137,14 @@ describe("Bulk user upload", () => {
cy.get(usersSelector.buttonAddUsers).click();
cy.get(usersSelector.buttonUploadCsvFile).click();
cy.get(usersSelector.inputFieldBulkUpload).selectFile(invite_users, {
force: true,
});
cy.get(usersSelector.uploadedFileData).should("contain", "invite_users");
cy.get(commonSelectors.cancelButton).click();
cy.get(usersSelector.buttonAddUsers).click();
cy.get(usersSelector.buttonUploadCsvFile).click();
cy.get(usersSelector.inputFieldBulkUpload).selectFile(invite_users, {
cy.get(usersSelector.inputFieldBulkUpload).selectFile(Validinvite, {
force: true,
});
cy.get(commonSelectors.fileSelector).should("contain", " 10usersupload");
cy.get(usersSelector.buttonUploadUsers).click();
cy.wait(30000);
cy.get(".go2072408551")
.should("be.visible")
.and("have.text", "250 users are being added");
.and("have.text", "10 users are being added");
common.searchUser("test12@gmail.com");
cy.contains("td", "test12@gmail.com")
.parent()

View file

@ -0,0 +1,84 @@
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
import * as signup from "Support/utils/selfHostSignUp";
import { logout } from "Support/utils/common";
import { onboardingSelectors } from "Selectors/onboarding";
//selfhostsetup
describe("Self host onboarding", () => {
beforeEach(() => {
cy.visit("/setup");
});
it("verify elements on self host onboarding page", () => {
cy.get(commonSelectors.HostBanner).should("be.visible");
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.adminSetup).should("be.visible");
cy.get(commonSelectors.signupTerms).should("be.visible");
cy.get(commonSelectors.userNameInputLabel).verifyVisibleElement(
"have.text",
commonText.userNameInputLabel
);
cy.get(commonSelectors.nameInputField).should("be.visible");
cy.get(commonSelectors.emailInputLabel).verifyVisibleElement(
"have.text",
commonText.emailInputLabel
);
cy.get(onboardingSelectors.emailInput).should("be.visible");
cy.get(commonSelectors.passwordLabel).verifyVisibleElement(
"have.text",
commonText.passwordLabel
);
cy.get(onboardingSelectors.passwordInput).should("be.visible");
cy.get(commonSelectors.passwordHelperTextSignup).verifyVisibleElement(
"have.text",
commonText.passwordHelperText
);
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
commonText.selfHostSignUpTermsHelperText
);
});
cy.get(commonSelectors.termsOfServiceLink)
.verifyVisibleElement("have.text", commonText.termsOfServiceLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/terms");
cy.get(commonSelectors.privacyPolicyLink)
.verifyVisibleElement("have.text", commonText.privacyPolicyLink)
.and("have.attr", "href")
.and("equal", "https://www.tooljet.com/privacy");
cy.clearAndType(commonSelectors.nameInputField, "The Developer");
cy.clearAndType(onboardingSelectors.emailInput, "dev@tooljet.io");
cy.clearAndType(onboardingSelectors.passwordInput, "password");
cy.get(commonSelectors.continueButton).click();
cy.get(commonSelectors.setUpworkspaceCheckPoint).verifyVisibleElement(
"have.text",
"Set up your workspace!"
);
cy.get(commonSelectors.workspaceNameInputLabel).verifyVisibleElement(
"have.text",
commonText.workspaceNameInputLabel
);
cy.get(commonSelectors.workspaceNameInputField).should("be.visible");
cy.clearAndType(commonSelectors.workspaceNameInputField, "My workspace");
cy.get(commonSelectors.OnbordingContinue).click();
cy.get(commonSelectors.skipbutton).click();
cy.get(commonSelectors.backLogo).click();
cy.get(commonSelectors.backtoapps).click();
logout();
cy.appUILogin();
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"
);
});
});

View file

@ -0,0 +1,187 @@
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
import { fake } from "Fixtures/fake";
import { addNewUser } from "Support/utils/onboarding";
import { logout } from "Support/utils/common";
import { onboardingSelectors } from "Selectors/onboarding";
describe("Password reset functionality", () => {
const data = {};
let passwordResetLink = "";
it("Verify wrong password limit", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase();
cy.defaultWorkspaceLogin();
addNewUser(data.firstName, data.email);
logout();
for (let i = 0; i < 5; i++) {
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "passw");
cy.get(onboardingSelectors.signInButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Invalid credentials"
);
}
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "passw");
cy.get(onboardingSelectors.signInButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Maximum password retry limit reached, please reset your password using forgot password option"
);
});
it("Verify forgot password page elements and functionality", () => {
cy.visit("/");
cy.get(commonSelectors.forgotPasswordLink).click();
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.forgotPasswordPageHeader).verifyVisibleElement(
"have.text",
commonText.forgotPasswordPageHeader
);
cy.get(commonSelectors.forgotPasswordPageSubHeader).verifyVisibleElement(
"have.text",
"New to ToolJet? Create an account"
);
cy.get(commonSelectors.createAnAccountLink).verifyVisibleElement(
"have.text",
commonText.createAnAccountLink
);
cy.get('[data-cy="email-input-field-label"]').verifyVisibleElement(
"have.text",
"Email address *"
);
cy.get('[data-cy="email-input-field-input"]').should("be.visible");
cy.get(commonSelectors.resetPasswordLinkButton)
.verifyVisibleElement("have.text", commonText.resetPasswordLinkButton)
.and("be.disabled");
cy.wait(5000);
cy.clearAndType('[data-cy="email-input-field-input"]', data.email);
cy.get(commonSelectors.resetPasswordLinkButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
commonText.passwordResetEmailToast
);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get('[data-cy="check-your-mail-header"]').verifyVisibleElement(
"have.text",
"Check your mail"
);
cy.get(commonSelectors.onboardingPageDescription).verifyVisibleElement(
"have.text",
commonText.resetPasswordEmailDescription(data.email)
);
cy.get(commonSelectors.spamMessage).verifyVisibleElement(
"have.text",
commonText.spamMessage
);
cy.get(commonSelectors.onboardingSeperator).should("be.visible");
cy.get(commonSelectors.onboardingSeperatorText).verifyVisibleElement(
"have.text",
commonText.onboardingSeperatorText
);
cy.get(commonSelectors.backToLoginButton).verifyVisibleElement(
"have.text",
commonText.backToLoginButton
);
cy.task("updateId", {
dbconfig: Cypress.env("app_db"),
sql: `select forgot_password_token from users where email='${data.email}';`,
}).then((resp) => {
passwordResetLink = `/reset-password/${resp.rows[0].forgot_password_token}`;
});
});
it("Verify reset password page and functionality", () => {
cy.visit(passwordResetLink);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.passwordResetPageHeader).verifyVisibleElement(
"have.text",
commonText.passwordResetPageHeader
);
cy.get(commonSelectors.newPasswordInputLabel).verifyVisibleElement(
"have.text",
commonText.newPasswordInputLabel
);
cy.get(commonSelectors.newPasswordInputField).should("be.visible");
cy.get(commonSelectors.passwordHelperText)
.eq(0)
.verifyVisibleElement("have.text", commonText.passwordHelperText);
cy.get(commonSelectors.confirmPasswordInputFieldLabel).verifyVisibleElement(
"have.text",
commonText.confirmPasswordInputFieldLabel
);
cy.get(commonSelectors.confirmPasswordInputField).should("be.visible");
cy.get(commonSelectors.passwordHelperText).verifyVisibleElement(
"have.text",
commonText.passwordHelperText
);
cy.get(commonSelectors.resetPasswordButton)
.verifyVisibleElement("have.text", commonText.resetPasswordButton)
.and("be.disabled");
cy.clearAndType(commonSelectors.newPasswordInputField, "Pass");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.get(commonSelectors.newPasswordInputField).clear();
cy.clearAndType(commonSelectors.confirmPasswordInputField, "Pass");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.clearAndType(commonSelectors.newPasswordInputField, "Pass");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "Pass");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.clearAndType(commonSelectors.newPasswordInputField, "password1");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "password");
cy.get(commonSelectors.resetPasswordButton).should("be.disabled");
cy.clearAndType(commonSelectors.newPasswordInputField, "Password");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "password");
cy.get('[data-cy="confirm-password-input-error"]').verifyVisibleElement(
"have.text",
"Passwords don't match"
);
cy.clearAndType(commonSelectors.newPasswordInputField, "Password");
cy.clearAndType(commonSelectors.confirmPasswordInputField, "Password");
cy.get(commonSelectors.resetPasswordButton).should("be.enabled").click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
commonText.passwordResetSuccessToast
);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get('[data-cy="password-has-been-reset-header"]').verifyVisibleElement(
"have.text",
commonText.passwordResetSuccessPageHeader
);
cy.get(commonSelectors.resetPasswordPageDescription).verifyVisibleElement(
"have.text",
commonText.resetPasswordPageDescription
);
cy.get(commonSelectors.backToLoginButton).verifyVisibleElement(
"have.text",
commonText.backToLoginButton
);
});
it("Verify user login using new password", () => {
cy.visit("/");
cy.clearAndType(onboardingSelectors.signupEmailInput, data.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "Password");
cy.get(onboardingSelectors.signInButton).click();
cy.get(commonSelectors.workspaceName).should("be.visible");
});
});

View file

@ -31,6 +31,7 @@ describe("dashboard", () => {
data.cloneAppName = `cloned-${data.appName}`;
data.updatedFolderName = `new-${data.folderName}`;
beforeEach(() => {
cy.intercept("GET", "/api/library_apps").as("appLibrary");
cy.intercept("DELETE", "/api/folders/*").as("folderDeleted");
@ -59,7 +60,7 @@ describe("dashboard", () => {
"My workspace"
);
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.editRectangleIcon).should("be.visible");
// cy.get(commonSelectors.editRectangleIcon).should("be.visible");
cy.get(commonSelectors.appCreateButton).verifyVisibleElement(
"have.text",
"Create an app"
@ -173,10 +174,14 @@ describe("dashboard", () => {
});
it("Should verify app card elements and app card operations", () => {
const customLayout = {
desktop: { top: 100, left: 20 },
mobile: { width: 8, height: 50 },
};
cy.apiLogin();
cy.apiCreateApp(data.appName);
cy.openApp();
cy.dragAndDropWidget("Table", 250, 250);
cy.addComponentToApp(data.appName, "text1", customLayout)
cy.backToApps();
@ -190,11 +195,8 @@ describe("dashboard", () => {
data.appName
);
cy.get(commonSelectors.appCreationDetails).should("be.visible");
cy.get(commonSelectors.appCreationDetails)
.should("be.visible")
.and(($el) => {
expect($el.contents().last().text().trim()).to.eq("The Developer");
});
//Add the edited details
});
viewAppCardOptions(data.appName);
@ -287,7 +289,7 @@ describe("dashboard", () => {
.and("have.text", dashboardText.appClonedToast);
cy.wait(3000);
cy.renameApp(data.cloneAppName);
cy.dragAndDropWidget("button", 25, 25);
cy.addComponentToApp(data.cloneAppName, "button", 25, 25);
cy.backToApps();
cy.wait("@appLibrary");
cy.wait(1000);
@ -339,11 +341,17 @@ describe("dashboard", () => {
});
it("Should verify the app CRUD operation", () => {
const customLayout = {
desktop: { top: 100, left: 20 },
mobile: { width: 8, height: 50 },
};
cy.skipWalkthrough();
data.appName = `${fake.companyName}-App`;
cy.defaultWorkspaceLogin();
cy.createApp(data.appName);
cy.dragAndDropWidget("Button", 450, 450);
cy.addComponentToApp(data.appName, "text1", customLayout)
cy.backToApps();
@ -353,7 +361,8 @@ describe("dashboard", () => {
);
navigateToAppEditor(data.appName);
cy.get(commonSelectors.canvas).should("contain", "Button");
// cy.get(commonSelectors.canvas).should("contain", "text1");
cy.get('.text-widget-section > div').should('be.visible')
cy.backToApps();
cy.wait("@appLibrary");
@ -366,10 +375,16 @@ describe("dashboard", () => {
});
it("Should verify the folder CRUD operation", () => {
const customLayout = {
desktop: { top: 100, left: 20 },
mobile: { width: 8, height: 50 },
};
data.appName = `${fake.companyName}-App`;
cy.defaultWorkspaceLogin();
cy.createApp(data.appName);
cy.dragAndDropWidget("Button", 100, 100);
cy.addComponentToApp(data.appName, "text1", customLayout)
cy.backToApps();

View file

@ -36,13 +36,12 @@ describe("Redirection error pages", () => {
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
cy.logoutApi();
cy.visit(`/applications/${data.lastName}`);
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.workEmailLabel).should("be.visible");
cy.wait(3000);
cy.apiLogin("test@tooljet.com", "password");
cy.visit(`/applications/${data.lastName}`);
cy.get(commonSelectors.backToHomeButton).click();
});
it("Verify error message in case of restricted access", () => {
@ -52,22 +51,22 @@ describe("Redirection error pages", () => {
cy.openApp();
cy.wait(1000);
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click();
cy.clearAndType(commonWidgetSelector.appNameSlugInput, data.slug);
cy.pause();
cy.wait(1000);
cy.logoutApi();
cy.apiLogin("test@tooljet.com", "password");
cy.visit(`/applications/${data.slug}`);
cy.pause();
cy.get(commonSelectors.modalHeader).verifyVisibleElement(
"have.text",
"Restricted access"
"App URL Unavailable"
);
cy.get(commonSelectors.modalDescription).verifyVisibleElement(
"have.text",
"You dont have access to this app. Kindly contact admin to know more."
"The app URL is currently unavailable because the app has not been released. Please either release it or contact admin for access."
);
cy.get(commonSelectors.backToHomeButton).verifyVisibleElement(
"have.text",
@ -79,7 +78,7 @@ describe("Redirection error pages", () => {
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
});
it.only("Verify error modal for app url of unreleased apps", () => {
it.skip("Verify error modal for app url of unreleased apps", () => {
data.appName = `${fake.companyName} App`;
data.slug = data.appName.toLowerCase().replace(/\s+/g, "-");
@ -111,7 +110,7 @@ describe("Redirection error pages", () => {
cy.url().should(
"eq",
`http://localhost:8082/error/url-unavailable?appSlug=${data.slug}`
`http://localhost:8082/error/restricted`
);
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
@ -123,11 +122,11 @@ describe("Redirection error pages", () => {
cy.visit(`http://localhost:8082/applications/${data.slug}`);
cy.get(commonSelectors.modalHeader).verifyVisibleElement(
"have.text",
"Restricted access"
"App URL Unavailable"
);
cy.get(commonSelectors.modalDescription).verifyVisibleElement(
"have.text",
"You dont have access to this app. Kindly contact admin to know more."
"The app URL is currently unavailable because the app has not been released. Please either release it or contact admin for access."
);
// cy.get('[data-cy="open-app-button"]').verifyVisibleElement("have.text", "Open app")
@ -174,7 +173,7 @@ describe("Redirection error pages", () => {
);
cy.url().should(
"eq",
`http://localhost:8082/error/url-unavailable?appSlug=${data.slug}`
`http://localhost:8082/error/restricted`
);
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");

View file

@ -1,149 +0,0 @@
import { commonSelectors } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { usersText } from "Texts/manageUsers";
import { usersSelector } from "Selectors/manageUsers";
import {
manageUsersElements,
fillUserInviteForm,
confirmInviteElements,
selectUserGroup,
inviteUserWithUserGroups,
fetchAndVisitInviteLink,
} from "Support/utils/manageUsers";
import {
navigateToManageUsers,
logout,
searchUser,
navigateToManageGroups,
} from "Support/utils/common";
import { updateWorkspaceName } from "Support/utils/userPermissions";
import { groupsSelector } from "Selectors/manageGroups";
import { groupsText } from "Texts/manageGroups";
import { addNewUser, visitWorkspaceInvitation, newInvite } from "Support/utils/onboarding";
import { commonText } from "Texts/common";
import { setSignupStatus, enableSignUp } from "Support/utils/manageSSO";
import { ssoSelector } from "Selectors/manageSSO";
import {
SignUpPageElements,
verifyConfirmEmailPage,
signUpLink,
verifyOnboardingQuestions,
} from "Support/utils/onboarding";
const data = {};
describe("user invite flow cases", () => {
beforeEach(() => {
cy.defaultWorkspaceLogin();
});
it("should verify the user signup after invited in a workspace", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.signUpName = fake.firstName;
data.workspaceName = fake.companyName;
setSignupStatus(true);
navigateToManageUsers();
fillUserInviteForm(data.firstName, data.email);
cy.get(usersSelector.buttonInviteUsers).click();
cy.logoutApi();
cy.visit("/");
cy.get(commonSelectors.createAnAccountLink).click();
SignUpPageElements();
cy.clearAndType(commonSelectors.nameInputField, data.signUpName);
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.signUpButton).click();
signUpLink(data.email);
cy.get(commonSelectors.setUpToolJetButton).click();
verifyOnboardingQuestions(data.signUpName, data.workspaceName);
visitWorkspaceInvitation(data.email, "My workspace");
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
cy.get(commonSelectors.loginButton).click();
cy.get(commonSelectors.invitedUserName).verifyVisibleElement(
"have.text",
data.signUpName
);
cy.get(commonSelectors.acceptInviteButton).click();
});
it("should verify the user signup after invited in a workspace", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.signUpName = fake.firstName;
data.workspaceName = fake.companyName;
setSignupStatus(true);
navigateToManageUsers();
fillUserInviteForm(data.firstName, data.email);
cy.get(usersSelector.buttonInviteUsers).click();
logout();
cy.get(ssoSelector.workspaceSubHeader).verifyVisibleElement(
"have.text",
"Sign in to your workspace - My workspace"
);
cy.get(commonSelectors.signInSubHeader).verifyVisibleElement(
"have.text",
"New to this workspace?Sign up"
);
cy.get(commonSelectors.createAnAccountLink).click();
SignUpPageElements();
cy.get(ssoSelector.workspaceSignUpHeader).verifyVisibleElement(
"have.text",
"Sign up to the workspace - My workspace"
);
cy.clearAndType(commonSelectors.nameInputField, data.signUpName);
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"The user is already registered. Please check your inbox for the activation link"
);
});
it("should verify exisiting user workspace signup", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
data.signUpName = fake.firstName;
data.workspaceName = fake.firstName.toLowerCase();
setSignupStatus(true);
navigateToManageUsers();
addNewUser(data.firstName, data.email);
logout();
cy.get(commonSelectors.createAnAccountLink).click();
cy.clearAndType(commonSelectors.nameInputField, data.firstName);
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"User already exists in the workspace."
);
cy.apiLogin();
cy.apiCreateWorkspace(data.workspaceName, data.workspaceName);
cy.visit(`${data.workspaceName}`);
cy.wait(3000)
setSignupStatus(true, data.workspaceName);
logout();
cy.get(commonSelectors.createAnAccountLink).click();
cy.clearAndType(commonSelectors.nameInputField, data.firstName);
cy.clearAndType(commonSelectors.emailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.defaultWorkspaceLogin();
visitWorkspaceInvitation(data.email, data.workspaceName);
cy.verifyToastMessage(commonSelectors.toastMessage, usersText.inviteToast);
logout();
});
});

View file

@ -5,6 +5,7 @@ import { profileText } from "Texts/profile";
import { commonSelectors } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { commonText } from "Texts/common";
import { onboardingSelectors } from "Selectors/onboarding";
describe("Profile Settings", () => {
const randomFirstName = fake.firstName;
@ -15,6 +16,7 @@ describe("Profile Settings", () => {
common.navigateToProfile();
});
// neeed to reset and seed bd after 1 run (as password changes will get 401 error )
it("Should verify the elements on profile settings page and name reset functionality", () => {
profile.profilePageElements();
@ -183,20 +185,16 @@ describe("Profile Settings", () => {
);
common.logout();
cy.clearAndType(commonSelectors.workEmailInputField, commonText.email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.get(commonSelectors.loginButton).click();
cy.clearAndType(onboardingSelectors.loginEmailInput, commonText.email);
cy.clearAndType(onboardingSelectors.loginPasswordInput, commonText.password);
cy.get(onboardingSelectors.signInButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
profileText.loginErrorToast
);
cy.clearAndType(
commonSelectors.passwordInputField,
profileText.newPassword
);
cy.get(commonSelectors.signInButton).click();
cy.clearAndType(onboardingSelectors.loginPasswordInput, profileText.newPassword);
cy.get(onboardingSelectors.signInButton).click();
common.navigateToProfile();
cy.clearAndType(
@ -213,7 +211,7 @@ describe("Profile Settings", () => {
common.logout();
cy.login(commonText.email, profileText.password);
cy.appUILogin(commonText.email, profileText.password);
common.logout();
});
});

View file

@ -0,0 +1,11 @@
First Name,Last Name,Email,User Role,Group
test1,user,test1@gmail.com,Builder,
test2,user,test3@gmail.com,End User,
Test3,Example,test12@gmail.com,Admin,
Test4,Example,test23@gmail.com,End User,
Test5,Example,test24@gmail.com,End User,
Test6,Example,test25@gmail.com,End User,
Test7,Example,test26@gmail.com,Admin,
Test8,Example,test27@gmail.com,Builder,
Test9,Example,test28@gmail.com,Builder,
Test10,Example,test29@gmail.com,End User,
1 First Name Last Name Email User Role Group
2 test1 user test1@gmail.com Builder
3 test2 user test3@gmail.com End User
4 Test3 Example test12@gmail.com Admin
5 Test4 Example test23@gmail.com End User
6 Test5 Example test24@gmail.com End User
7 Test6 Example test25@gmail.com End User
8 Test7 Example test26@gmail.com Admin
9 Test8 Example test27@gmail.com Builder
10 Test9 Example test28@gmail.com Builder
11 Test10 Example test29@gmail.com End User

View file

@ -1,499 +1,252 @@
First Name,Last Name,Email,Groups
Vijay,Yadav,vjyaav12@gmail.com,All Users|Admin
Vijay,Yadav,vjyaav13@gmail.com,All Users
Vijay,Yadav,vjyaav14@gmail.com,All Users
Vijay,Yadav,vjyaav15@gmail.com,All Users
Vijay,Yadav,vjyaav16@gmail.com,All Users
Vijay,Yadav,vjyaav17@gmail.com,All Users
Vijay,Yadav,vjyaav18@gmail.com,All Users
Vijay,Yadav,vjyaav19@gmail.com,All Users
Vijay,Yadav,vjyaav20@gmail.com,All Users
Vijay,Yadav,vjyaav21@gmail.com,All Users
Vijay,Yadav,vjyaav22@gmail.com,All Users
Vijay,Yadav,vjyaav23@gmail.com,All Users
Vijay,Yadav,vjyaav24@gmail.com,All Users
Vijay,Yadav,vjyaav25@gmail.com,All Users
Vijay,Yadav,vjyaav26@gmail.com,All Users
Vijay,Yadav,vjyaav27@gmail.com,All Users
Vijay,Yadav,vjyaav28@gmail.com,All Users
Vijay,Yadav,vjyaav29@gmail.com,All Users
Vijay,Yadav,vjyaav30@gmail.com,All Users
Vijay,Yadav,vjyaav31@gmail.com,All Users
Vijay,Yadav,vjyaav32@gmail.com,All Users
Vijay,Yadav,vjyaav33@gmail.com,All Users
Vijay,Yadav,vjyaav34@gmail.com,All Users
Vijay,Yadav,vjyaav35@gmail.com,All Users
Vijay,Yadav,vjyaav36@gmail.com,All Users
Vijay,Yadav,vjyaav37@gmail.com,All Users
Vijay,Yadav,vjyaav38@gmail.com,All Users
Vijay,Yadav,vjyaav39@gmail.com,All Users
Vijay,Yadav,vjyaav40@gmail.com,All Users
Vijay,Yadav,vjyaav41@gmail.com,All Users
Vijay,Yadav,vjyaav42@gmail.com,All Users
Vijay,Yadav,vjyaav43@gmail.com,All Users
Vijay,Yadav,vjyaav44@gmail.com,All Users
Vijay,Yadav,vjyaav45@gmail.com,All Users
Vijay,Yadav,vjyaav46@gmail.com,All Users
Vijay,Yadav,vjyaav47@gmail.com,All Users
Vijay,Yadav,vjyaav48@gmail.com,All Users
Vijay,Yadav,vjyaav49@gmail.com,All Users
Vijay,Yadav,vjyaav50@gmail.com,All Users
Vijay,Yadav,vjyaav51@gmail.com,All Users
Vijay,Yadav,vjyaav52@gmail.com,All Users
Vijay,Yadav,vjyaav53@gmail.com,All Users
Vijay,Yadav,vjyaav54@gmail.com,All Users
Vijay,Yadav,vjyaav55@gmail.com,All Users
Vijay,Yadav,vjyaav56@gmail.com,All Users
Vijay,Yadav,vjyaav57@gmail.com,All Users
Vijay,Yadav,vjyaav58@gmail.com,All Users
Vijay,Yadav,vjyaav59@gmail.com,All Users
Vijay,Yadav,vjyaav60@gmail.com,All Users
Vijay,Yadav,vjyaav61@gmail.com,All Users
Vijay,Yadav,vjyaav62@gmail.com,All Users
Vijay,Yadav,vjyaav63@gmail.com,All Users
Vijay,Yadav,vjyaav64@gmail.com,All Users
Vijay,Yadav,vjyaav65@gmail.com,All Users
Vijay,Yadav,vjyaav66@gmail.com,All Users
Vijay,Yadav,vjyaav67@gmail.com,All Users
Vijay,Yadav,vjyaav68@gmail.com,All Users
Vijay,Yadav,vjyaav69@gmail.com,All Users
Vijay,Yadav,vjyaav70@gmail.com,All Users
Vijay,Yadav,vjyaav71@gmail.com,All Users
Vijay,Yadav,vjyaav72@gmail.com,All Users
Vijay,Yadav,vjyaav73@gmail.com,All Users
Vijay,Yadav,vjyaav74@gmail.com,All Users
Vijay,Yadav,vjyaav75@gmail.com,All Users
Vijay,Yadav,vjyaav76@gmail.com,All Users
Vijay,Yadav,vjyaav77@gmail.com,All Users
Vijay,Yadav,vjyaav78@gmail.com,All Users
Vijay,Yadav,vjyaav79@gmail.com,All Users
Vijay,Yadav,vjyaav80@gmail.com,All Users
Vijay,Yadav,vjyaav81@gmail.com,All Users
Vijay,Yadav,vjyaav82@gmail.com,All Users
Vijay,Yadav,vjyaav83@gmail.com,All Users
Vijay,Yadav,vjyaav84@gmail.com,All Users
Vijay,Yadav,vjyaav85@gmail.com,All Users
Vijay,Yadav,vjyaav86@gmail.com,All Users
Vijay,Yadav,vjyaav87@gmail.com,All Users
Vijay,Yadav,vjyaav88@gmail.com,All Users
Vijay,Yadav,vjyaav89@gmail.com,All Users
Vijay,Yadav,vjyaav90@gmail.com,All Users
Vijay,Yadav,vjyaav91@gmail.com,All Users
Vijay,Yadav,vjyaav92@gmail.com,All Users
Vijay,Yadav,vjyaav93@gmail.com,All Users
Vijay,Yadav,vjyaav94@gmail.com,All Users
Vijay,Yadav,vjyaav95@gmail.com,All Users
Vijay,Yadav,vjyaav96@gmail.com,All Users
Vijay,Yadav,vjyaav97@gmail.com,All Users
Vijay,Yadav,vjyaav98@gmail.com,All Users
Vijay,Yadav,vjyaav99@gmail.com,All Users
Vijay,Yadav,vjyaav100@gmail.com,All Users
Vijay,Yadav,vjyaav101@gmail.com,All Users
Vijay,Yadav,vjyaav102@gmail.com,All Users
Vijay,Yadav,vjyaav103@gmail.com,All Users
Vijay,Yadav,vjyaav104@gmail.com,All Users
Vijay,Yadav,vjyaav105@gmail.com,All Users
Vijay,Yadav,vjyaav106@gmail.com,All Users
Vijay,Yadav,vjyaav107@gmail.com,All Users
Vijay,Yadav,vjyaav108@gmail.com,All Users
Vijay,Yadav,vjyaav109@gmail.com,All Users
Vijay,Yadav,vjyaav110@gmail.com,All Users
Vijay,Yadav,vjyaav111@gmail.com,All Users
Vijay,Yadav,vjyaav112@gmail.com,All Users
Vijay,Yadav,vjyaav113@gmail.com,All Users
Vijay,Yadav,vjyaav114@gmail.com,All Users
Vijay,Yadav,vjyaav115@gmail.com,All Users
Vijay,Yadav,vjyaav116@gmail.com,All Users
Vijay,Yadav,vjyaav117@gmail.com,All Users
Vijay,Yadav,vjyaav118@gmail.com,All Users
Vijay,Yadav,vjyaav119@gmail.com,All Users
Vijay,Yadav,vjyaav120@gmail.com,All Users
Vijay,Yadav,vjyaav121@gmail.com,All Users
Vijay,Yadav,vjyaav122@gmail.com,All Users
Vijay,Yadav,vjyaav123@gmail.com,All Users
Vijay,Yadav,vjyaav124@gmail.com,All Users
Vijay,Yadav,vjyaav125@gmail.com,All Users
Vijay,Yadav,vjyaav126@gmail.com,All Users
Vijay,Yadav,vjyaav127@gmail.com,All Users
Vijay,Yadav,vjyaav128@gmail.com,All Users
Vijay,Yadav,vjyaav129@gmail.com,All Users
Vijay,Yadav,vjyaav130@gmail.com,All Users
Vijay,Yadav,vjyaav131@gmail.com,All Users
Vijay,Yadav,vjyaav132@gmail.com,All Users
Vijay,Yadav,vjyaav133@gmail.com,All Users
Vijay,Yadav,vjyaav134@gmail.com,All Users
Vijay,Yadav,vjyaav135@gmail.com,All Users
Vijay,Yadav,vjyaav136@gmail.com,All Users
Vijay,Yadav,vjyaav137@gmail.com,All Users
Vijay,Yadav,vjyaav138@gmail.com,All Users
Vijay,Yadav,vjyaav139@gmail.com,All Users
Vijay,Yadav,vjyaav140@gmail.com,All Users
Vijay,Yadav,vjyaav141@gmail.com,All Users
Vijay,Yadav,vjyaav142@gmail.com,All Users
Vijay,Yadav,vjyaav143@gmail.com,All Users
Vijay,Yadav,vjyaav144@gmail.com,All Users
Vijay,Yadav,vjyaav145@gmail.com,All Users
Vijay,Yadav,vjyaav146@gmail.com,All Users
Vijay,Yadav,vjyaav147@gmail.com,All Users
Vijay,Yadav,vjyaav148@gmail.com,All Users
Vijay,Yadav,vjyaav149@gmail.com,All Users
Vijay,Yadav,vjyaav150@gmail.com,All Users
Vijay,Yadav,vjyaav151@gmail.com,All Users
Vijay,Yadav,vjyaav152@gmail.com,All Users
Vijay,Yadav,vjyaav153@gmail.com,All Users
Vijay,Yadav,vjyaav154@gmail.com,All Users
Vijay,Yadav,vjyaav155@gmail.com,All Users
Vijay,Yadav,vjyaav156@gmail.com,All Users
Vijay,Yadav,vjyaav157@gmail.com,All Users
Vijay,Yadav,vjyaav158@gmail.com,All Users
Vijay,Yadav,vjyaav159@gmail.com,All Users
Vijay,Yadav,vjyaav160@gmail.com,All Users
Vijay,Yadav,vjyaav161@gmail.com,All Users
Vijay,Yadav,vjyaav162@gmail.com,All Users
Vijay,Yadav,vjyaav163@gmail.com,All Users
Vijay,Yadav,vjyaav164@gmail.com,All Users
Vijay,Yadav,vjyaav165@gmail.com,All Users
Vijay,Yadav,vjyaav166@gmail.com,All Users
Vijay,Yadav,vjyaav167@gmail.com,All Users
Vijay,Yadav,vjyaav168@gmail.com,All Users
Vijay,Yadav,vjyaav169@gmail.com,All Users
Vijay,Yadav,vjyaav170@gmail.com,All Users
Vijay,Yadav,vjyaav171@gmail.com,All Users
Vijay,Yadav,vjyaav172@gmail.com,All Users
Vijay,Yadav,vjyaav173@gmail.com,All Users
Vijay,Yadav,vjyaav174@gmail.com,All Users
Vijay,Yadav,vjyaav175@gmail.com,All Users
Vijay,Yadav,vjyaav176@gmail.com,All Users
Vijay,Yadav,vjyaav177@gmail.com,All Users
Vijay,Yadav,vjyaav178@gmail.com,All Users
Vijay,Yadav,vjyaav179@gmail.com,All Users
Vijay,Yadav,vjyaav180@gmail.com,All Users
Vijay,Yadav,vjyaav181@gmail.com,All Users
Vijay,Yadav,vjyaav182@gmail.com,All Users
Vijay,Yadav,vjyaav183@gmail.com,All Users
Vijay,Yadav,vjyaav184@gmail.com,All Users
Vijay,Yadav,vjyaav185@gmail.com,All Users
Vijay,Yadav,vjyaav186@gmail.com,All Users
Vijay,Yadav,vjyaav187@gmail.com,All Users
Vijay,Yadav,vjyaav188@gmail.com,All Users
Vijay,Yadav,vjyaav189@gmail.com,All Users
Vijay,Yadav,vjyaav190@gmail.com,All Users
Vijay,Yadav,vjyaav191@gmail.com,All Users
Vijay,Yadav,vjyaav192@gmail.com,All Users
Vijay,Yadav,vjyaav193@gmail.com,All Users
Vijay,Yadav,vjyaav194@gmail.com,All Users
Vijay,Yadav,vjyaav195@gmail.com,All Users
Vijay,Yadav,vjyaav196@gmail.com,All Users
Vijay,Yadav,vjyaav197@gmail.com,All Users
Vijay,Yadav,vjyaav198@gmail.com,All Users
Vijay,Yadav,vjyaav199@gmail.com,All Users
Vijay,Yadav,vjyaav200@gmail.com,All Users
Vijay,Yadav,vjyaav201@gmail.com,All Users
Vijay,Yadav,vjyaav202@gmail.com,All Users
Vijay,Yadav,vjyaav203@gmail.com,All Users
Vijay,Yadav,vjyaav204@gmail.com,All Users
Vijay,Yadav,vjyaav205@gmail.com,All Users
Vijay,Yadav,vjyaav206@gmail.com,All Users
Vijay,Yadav,vjyaav207@gmail.com,All Users
Vijay,Yadav,vjyaav208@gmail.com,All Users
Vijay,Yadav,vjyaav209@gmail.com,All Users
Vijay,Yadav,vjyaav210@gmail.com,All Users
Vijay,Yadav,vjyaav211@gmail.com,All Users
Vijay,Yadav,vjyaav212@gmail.com,All Users
Vijay,Yadav,vjyaav213@gmail.com,All Users
Vijay,Yadav,vjyaav214@gmail.com,All Users
Vijay,Yadav,vjyaav215@gmail.com,All Users
Vijay,Yadav,vjyaav216@gmail.com,All Users
Vijay,Yadav,vjyaav217@gmail.com,All Users
Vijay,Yadav,vjyaav218@gmail.com,All Users
Vijay,Yadav,vjyaav219@gmail.com,All Users
Vijay,Yadav,vjyaav220@gmail.com,All Users
Vijay,Yadav,vjyaav221@gmail.com,All Users
Vijay,Yadav,vjyaav222@gmail.com,All Users
Vijay,Yadav,vjyaav223@gmail.com,All Users
Vijay,Yadav,vjyaav224@gmail.com,All Users
Vijay,Yadav,vjyaav225@gmail.com,All Users
Vijay,Yadav,vjyaav226@gmail.com,All Users
Vijay,Yadav,vjyaav227@gmail.com,All Users
Vijay,Yadav,vjyaav228@gmail.com,All Users
Vijay,Yadav,vjyaav229@gmail.com,All Users
Vijay,Yadav,vjyaav230@gmail.com,All Users
Vijay,Yadav,vjyaav231@gmail.com,All Users
Vijay,Yadav,vjyaav232@gmail.com,All Users
Vijay,Yadav,vjyaav233@gmail.com,All Users
Vijay,Yadav,vjyaav234@gmail.com,All Users
Vijay,Yadav,vjyaav235@gmail.com,All Users
Vijay,Yadav,vjyaav236@gmail.com,All Users
Vijay,Yadav,vjyaav237@gmail.com,All Users
Vijay,Yadav,vjyaav238@gmail.com,All Users
Vijay,Yadav,vjyaav239@gmail.com,All Users
Vijay,Yadav,vjyaav240@gmail.com,All Users
Vijay,Yadav,vjyaav241@gmail.com,All Users
Vijay,Yadav,vjyaav242@gmail.com,All Users
Vijay,Yadav,vjyaav243@gmail.com,All Users
Vijay,Yadav,vjyaav244@gmail.com,All Users
Vijay,Yadav,vjyaav245@gmail.com,All Users
Vijay,Yadav,vjyaav246@gmail.com,All Users
Vijay,Yadav,vjyaav247@gmail.com,All Users
Vijay,Yadav,vjyaav248@gmail.com,All Users
Vijay,Yadav,vjyaav249@gmail.com,All Users
Vijay,Yadav,vjyaav250@gmail.com,All Users
Vijay,Yadav,vjyaav251@gmail.com,All Users
Vijay,Yadav,vjyaav252@gmail.com,All Users
Vijay,Yadav,vjyaav253@gmail.com,All Users
Vijay,Yadav,vjyaav254@gmail.com,All Users
Vijay,Yadav,vjyaav255@gmail.com,All Users
Vijay,Yadav,vjyaav256@gmail.com,All Users
Vijay,Yadav,vjyaav257@gmail.com,All Users
Vijay,Yadav,vjyaav258@gmail.com,All Users
Vijay,Yadav,vjyaav259@gmail.com,All Users
Vijay,Yadav,vjyaav260@gmail.com,All Users
Vijay,Yadav,vjyaav261@gmail.com,All Users
Vijay,Yadav,vjyaav262@gmail.com,All Users
Vijay,Yadav,vjyaav263@gmail.com,All Users
Vijay,Yadav,vjyaav264@gmail.com,All Users
Vijay,Yadav,vjyaav265@gmail.com,All Users
Vijay,Yadav,vjyaav266@gmail.com,All Users
Vijay,Yadav,vjyaav267@gmail.com,All Users
Vijay,Yadav,vjyaav268@gmail.com,All Users
Vijay,Yadav,vjyaav269@gmail.com,All Users
Vijay,Yadav,vjyaav270@gmail.com,All Users
Vijay,Yadav,vjyaav271@gmail.com,All Users
Vijay,Yadav,vjyaav272@gmail.com,All Users
Vijay,Yadav,vjyaav273@gmail.com,All Users
Vijay,Yadav,vjyaav274@gmail.com,All Users
Vijay,Yadav,vjyaav275@gmail.com,All Users
Vijay,Yadav,vjyaav276@gmail.com,All Users
Vijay,Yadav,vjyaav277@gmail.com,All Users
Vijay,Yadav,vjyaav278@gmail.com,All Users
Vijay,Yadav,vjyaav279@gmail.com,All Users
Vijay,Yadav,vjyaav280@gmail.com,All Users
Vijay,Yadav,vjyaav281@gmail.com,All Users
Vijay,Yadav,vjyaav282@gmail.com,All Users
Vijay,Yadav,vjyaav283@gmail.com,All Users
Vijay,Yadav,vjyaav284@gmail.com,All Users
Vijay,Yadav,vjyaav285@gmail.com,All Users
Vijay,Yadav,vjyaav286@gmail.com,All Users
Vijay,Yadav,vjyaav287@gmail.com,All Users
Vijay,Yadav,vjyaav288@gmail.com,All Users
Vijay,Yadav,vjyaav289@gmail.com,All Users
Vijay,Yadav,vjyaav290@gmail.com,All Users
Vijay,Yadav,vjyaav291@gmail.com,All Users
Vijay,Yadav,vjyaav292@gmail.com,All Users
Vijay,Yadav,vjyaav293@gmail.com,All Users
Vijay,Yadav,vjyaav294@gmail.com,All Users
Vijay,Yadav,vjyaav295@gmail.com,All Users
Vijay,Yadav,vjyaav296@gmail.com,All Users
Vijay,Yadav,vjyaav297@gmail.com,All Users
Vijay,Yadav,vjyaav298@gmail.com,All Users
Vijay,Yadav,vjyaav299@gmail.com,All Users
Vijay,Yadav,vjyaav300@gmail.com,All Users
Vijay,Yadav,vjyaav301@gmail.com,All Users
Vijay,Yadav,vjyaav302@gmail.com,All Users
Vijay,Yadav,vjyaav303@gmail.com,All Users
Vijay,Yadav,vjyaav304@gmail.com,All Users
Vijay,Yadav,vjyaav305@gmail.com,All Users
Vijay,Yadav,vjyaav306@gmail.com,All Users
Vijay,Yadav,vjyaav307@gmail.com,All Users
Vijay,Yadav,vjyaav308@gmail.com,All Users
Vijay,Yadav,vjyaav309@gmail.com,All Users
Vijay,Yadav,vjyaav310@gmail.com,All Users
Vijay,Yadav,vjyaav311@gmail.com,All Users
Vijay,Yadav,vjyaav312@gmail.com,All Users
Vijay,Yadav,vjyaav313@gmail.com,All Users
Vijay,Yadav,vjyaav314@gmail.com,All Users
Vijay,Yadav,vjyaav315@gmail.com,All Users
Vijay,Yadav,vjyaav316@gmail.com,All Users
Vijay,Yadav,vjyaav317@gmail.com,All Users
Vijay,Yadav,vjyaav318@gmail.com,All Users
Vijay,Yadav,vjyaav319@gmail.com,All Users
Vijay,Yadav,vjyaav320@gmail.com,All Users
Vijay,Yadav,vjyaav321@gmail.com,All Users
Vijay,Yadav,vjyaav322@gmail.com,All Users
Vijay,Yadav,vjyaav323@gmail.com,All Users
Vijay,Yadav,vjyaav324@gmail.com,All Users
Vijay,Yadav,vjyaav325@gmail.com,All Users
Vijay,Yadav,vjyaav326@gmail.com,All Users
Vijay,Yadav,vjyaav327@gmail.com,All Users
Vijay,Yadav,vjyaav328@gmail.com,All Users
Vijay,Yadav,vjyaav329@gmail.com,All Users
Vijay,Yadav,vjyaav330@gmail.com,All Users
Vijay,Yadav,vjyaav331@gmail.com,All Users
Vijay,Yadav,vjyaav332@gmail.com,All Users
Vijay,Yadav,vjyaav333@gmail.com,All Users
Vijay,Yadav,vjyaav334@gmail.com,All Users
Vijay,Yadav,vjyaav335@gmail.com,All Users
Vijay,Yadav,vjyaav336@gmail.com,All Users
Vijay,Yadav,vjyaav337@gmail.com,All Users
Vijay,Yadav,vjyaav338@gmail.com,All Users
Vijay,Yadav,vjyaav339@gmail.com,All Users
Vijay,Yadav,vjyaav340@gmail.com,All Users
Vijay,Yadav,vjyaav341@gmail.com,All Users
Vijay,Yadav,vjyaav342@gmail.com,All Users
Vijay,Yadav,vjyaav343@gmail.com,All Users
Vijay,Yadav,vjyaav344@gmail.com,All Users
Vijay,Yadav,vjyaav345@gmail.com,All Users
Vijay,Yadav,vjyaav346@gmail.com,All Users
Vijay,Yadav,vjyaav347@gmail.com,All Users
Vijay,Yadav,vjyaav348@gmail.com,All Users
Vijay,Yadav,vjyaav349@gmail.com,All Users
Vijay,Yadav,vjyaav350@gmail.com,All Users
Vijay,Yadav,vjyaav351@gmail.com,All Users
Vijay,Yadav,vjyaav352@gmail.com,All Users
Vijay,Yadav,vjyaav353@gmail.com,All Users
Vijay,Yadav,vjyaav354@gmail.com,All Users
Vijay,Yadav,vjyaav355@gmail.com,All Users
Vijay,Yadav,vjyaav356@gmail.com,All Users
Vijay,Yadav,vjyaav357@gmail.com,All Users
Vijay,Yadav,vjyaav358@gmail.com,All Users
Vijay,Yadav,vjyaav359@gmail.com,All Users
Vijay,Yadav,vjyaav360@gmail.com,All Users
Vijay,Yadav,vjyaav361@gmail.com,All Users
Vijay,Yadav,vjyaav362@gmail.com,All Users
Vijay,Yadav,vjyaav363@gmail.com,All Users
Vijay,Yadav,vjyaav364@gmail.com,All Users
Vijay,Yadav,vjyaav365@gmail.com,All Users
Vijay,Yadav,vjyaav366@gmail.com,All Users
Vijay,Yadav,vjyaav367@gmail.com,All Users
Vijay,Yadav,vjyaav368@gmail.com,All Users
Vijay,Yadav,vjyaav369@gmail.com,All Users
Vijay,Yadav,vjyaav370@gmail.com,All Users
Vijay,Yadav,vjyaav371@gmail.com,All Users
Vijay,Yadav,vjyaav372@gmail.com,All Users
Vijay,Yadav,vjyaav373@gmail.com,All Users
Vijay,Yadav,vjyaav374@gmail.com,All Users
Vijay,Yadav,vjyaav375@gmail.com,All Users
Vijay,Yadav,vjyaav376@gmail.com,All Users
Vijay,Yadav,vjyaav377@gmail.com,All Users
Vijay,Yadav,vjyaav378@gmail.com,All Users
Vijay,Yadav,vjyaav379@gmail.com,All Users
Vijay,Yadav,vjyaav380@gmail.com,All Users
Vijay,Yadav,vjyaav381@gmail.com,All Users
Vijay,Yadav,vjyaav382@gmail.com,All Users
Vijay,Yadav,vjyaav383@gmail.com,All Users
Vijay,Yadav,vjyaav384@gmail.com,All Users
Vijay,Yadav,vjyaav385@gmail.com,All Users
Vijay,Yadav,vjyaav386@gmail.com,All Users
Vijay,Yadav,vjyaav387@gmail.com,All Users
Vijay,Yadav,vjyaav388@gmail.com,All Users
Vijay,Yadav,vjyaav389@gmail.com,All Users
Vijay,Yadav,vjyaav390@gmail.com,All Users
Vijay,Yadav,vjyaav391@gmail.com,All Users
Vijay,Yadav,vjyaav392@gmail.com,All Users
Vijay,Yadav,vjyaav393@gmail.com,All Users
Vijay,Yadav,vjyaav394@gmail.com,All Users
Vijay,Yadav,vjyaav395@gmail.com,All Users
Vijay,Yadav,vjyaav396@gmail.com,All Users
Vijay,Yadav,vjyaav397@gmail.com,All Users
Vijay,Yadav,vjyaav398@gmail.com,All Users
Vijay,Yadav,vjyaav399@gmail.com,All Users
Vijay,Yadav,vjyaav400@gmail.com,All Users
Vijay,Yadav,vjyaav401@gmail.com,All Users
Vijay,Yadav,vjyaav402@gmail.com,All Users
Vijay,Yadav,vjyaav403@gmail.com,All Users
Vijay,Yadav,vjyaav404@gmail.com,All Users
Vijay,Yadav,vjyaav405@gmail.com,All Users
Vijay,Yadav,vjyaav406@gmail.com,All Users
Vijay,Yadav,vjyaav407@gmail.com,All Users
Vijay,Yadav,vjyaav408@gmail.com,All Users
Vijay,Yadav,vjyaav409@gmail.com,All Users
Vijay,Yadav,vjyaav410@gmail.com,All Users
Vijay,Yadav,vjyaav411@gmail.com,All Users
Vijay,Yadav,vjyaav412@gmail.com,All Users
Vijay,Yadav,vjyaav413@gmail.com,All Users
Vijay,Yadav,vjyaav414@gmail.com,All Users
Vijay,Yadav,vjyaav415@gmail.com,All Users
Vijay,Yadav,vjyaav416@gmail.com,All Users
Vijay,Yadav,vjyaav417@gmail.com,All Users
Vijay,Yadav,vjyaav418@gmail.com,All Users
Vijay,Yadav,vjyaav419@gmail.com,All Users
Vijay,Yadav,vjyaav420@gmail.com,All Users
Vijay,Yadav,vjyaav421@gmail.com,All Users
Vijay,Yadav,vjyaav422@gmail.com,All Users
Vijay,Yadav,vjyaav423@gmail.com,All Users
Vijay,Yadav,vjyaav424@gmail.com,All Users
Vijay,Yadav,vjyaav425@gmail.com,All Users
Vijay,Yadav,vjyaav426@gmail.com,All Users
Vijay,Yadav,vjyaav427@gmail.com,All Users
Vijay,Yadav,vjyaav428@gmail.com,All Users
Vijay,Yadav,vjyaav429@gmail.com,All Users
Vijay,Yadav,vjyaav430@gmail.com,All Users
Vijay,Yadav,vjyaav431@gmail.com,All Users
Vijay,Yadav,vjyaav432@gmail.com,All Users
Vijay,Yadav,vjyaav433@gmail.com,All Users
Vijay,Yadav,vjyaav434@gmail.com,All Users
Vijay,Yadav,vjyaav435@gmail.com,All Users
Vijay,Yadav,vjyaav436@gmail.com,All Users
Vijay,Yadav,vjyaav437@gmail.com,All Users
Vijay,Yadav,vjyaav438@gmail.com,All Users
Vijay,Yadav,vjyaav439@gmail.com,All Users
Vijay,Yadav,vjyaav440@gmail.com,All Users
Vijay,Yadav,vjyaav441@gmail.com,All Users
Vijay,Yadav,vjyaav442@gmail.com,All Users
Vijay,Yadav,vjyaav443@gmail.com,All Users
Vijay,Yadav,vjyaav444@gmail.com,All Users
Vijay,Yadav,vjyaav445@gmail.com,All Users
Vijay,Yadav,vjyaav446@gmail.com,All Users
Vijay,Yadav,vjyaav447@gmail.com,All Users
Vijay,Yadav,vjyaav448@gmail.com,All Users
Vijay,Yadav,vjyaav449@gmail.com,All Users
Vijay,Yadav,vjyaav450@gmail.com,All Users
Vijay,Yadav,vjyaav451@gmail.com,All Users
Vijay,Yadav,vjyaav452@gmail.com,All Users
Vijay,Yadav,vjyaav453@gmail.com,All Users
Vijay,Yadav,vjyaav454@gmail.com,All Users
Vijay,Yadav,vjyaav455@gmail.com,All Users
Vijay,Yadav,vjyaav456@gmail.com,All Users
Vijay,Yadav,vjyaav457@gmail.com,All Users
Vijay,Yadav,vjyaav458@gmail.com,All Users
Vijay,Yadav,vjyaav459@gmail.com,All Users
Vijay,Yadav,vjyaav460@gmail.com,All Users
Vijay,Yadav,vjyaav461@gmail.com,All Users
Vijay,Yadav,vjyaav462@gmail.com,All Users
Vijay,Yadav,vjyaav463@gmail.com,All Users
Vijay,Yadav,vjyaav464@gmail.com,All Users
Vijay,Yadav,vjyaav465@gmail.com,All Users
Vijay,Yadav,vjyaav466@gmail.com,All Users
Vijay,Yadav,vjyaav467@gmail.com,All Users
Vijay,Yadav,vjyaav468@gmail.com,All Users
Vijay,Yadav,vjyaav469@gmail.com,All Users
Vijay,Yadav,vjyaav470@gmail.com,All Users
Vijay,Yadav,vjyaav471@gmail.com,All Users
Vijay,Yadav,vjyaav472@gmail.com,All Users
Vijay,Yadav,vjyaav473@gmail.com,All Users
Vijay,Yadav,vjyaav474@gmail.com,All Users
Vijay,Yadav,vjyaav475@gmail.com,All Users
Vijay,Yadav,vjyaav476@gmail.com,All Users
Vijay,Yadav,vjyaav477@gmail.com,All Users
Vijay,Yadav,vjyaav478@gmail.com,All Users
Vijay,Yadav,vjyaav479@gmail.com,All Users
Vijay,Yadav,vjyaav480@gmail.com,All Users
Vijay,Yadav,vjyaav481@gmail.com,All Users
Vijay,Yadav,vjyaav482@gmail.com,All Users
Vijay,Yadav,vjyaav483@gmail.com,All Users
Vijay,Yadav,vjyaav484@gmail.com,All Users
Vijay,Yadav,vjyaav485@gmail.com,All Users
Vijay,Yadav,vjyaav486@gmail.com,All Users
Vijay,Yadav,vjyaav487@gmail.com,All Users
Vijay,Yadav,vjyaav488@gmail.com,All Users
Vijay,Yadav,vjyaav489@gmail.com,All Users
Vijay,Yadav,vjyaav490@gmail.com,All Users
Vijay,Yadav,vjyaav491@gmail.com,All Users
Vijay,Yadav,vjyaav492@gmail.com,All Users
Vijay,Yadav,vjyaav493@gmail.com,All Users
Vijay,Yadav,vjyaav494@gmail.com,All Users
Vijay,Yadav,vjyaav495@gmail.com,All Users
Vijay,Yadav,vjyaav496@gmail.com,All Users
Vijay,Yadav,vjyaav497@gmail.com,All Users
Vijay,Yadav,vjyaav498@gmail.com,All Users
Vijay,Yadav,vjyaav499@gmail.com,All Users
Vijay,Yadav,vjyaav500@gmail.com,All Users
Vijay,Yadav,vjyaav501@gmail.com,All Users
Vijay,Yadav,vjyaav502@gmail.com,All Users
Vijay,Yadav,vjyaav503@gmail.com,All Users
Vijay,Yadav,vjyaav504@gmail.com,All Users
Vijay,Yadav,vjyaav505@gmail.com,All Users
Vijay,Yadav,vjyaav506@gmail.com,All Users
Vijay,Yadav,vjyaav507@gmail.com,All Users
Vijay,Yadav,vjyaav508@gmail.com,All Users
Vijay,Yadav,vjyaav509@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
Vijay,Yadav,vjyaav1@gmail.com,Admin,
Vijay,Yadav,vjyaav2@gmail.com,Builder,
Vijay,Yadav,vjyaav3@gmail.com,Builder,
Vijay,Yadav,vjyaav4@gmail.com,End User,
Vijay,Yadav,vjyaav5@gmail.com,End User,
Vijay,Yadav,vjyaav6@gmail.com,End User,
Vijay,Yadav,vjyaav7@gmail.com,End User,
Vijay,Yadav,vjyaav8@gmail.com,End User,
Vijay,Yadav,vjyaav9@gmail.com,End User,
Vijay,Yadav,vjyaav10@gmail.com,End User,
Vijay,Yadav,vjyaav11@gmail.com,End User,
Vijay,Yadav,vjyaav12@gmail.com,End User,
Vijay,Yadav,vjyaav13@gmail.com,End User,
Vijay,Yadav,vjyaav14@gmail.com,End User,
Vijay,Yadav,vjyaav15@gmail.com,End User,
Vijay,Yadav,vjyaav16@gmail.com,End User,
Vijay,Yadav,vjyaav17@gmail.com,End User,
Vijay,Yadav,vjyaav18@gmail.com,End User,
Vijay,Yadav,vjyaav19@gmail.com,End User,
Vijay,Yadav,vjyaav20@gmail.com,End User,
Vijay,Yadav,vjyaav21@gmail.com,End User,
Vijay,Yadav,vjyaav22@gmail.com,End User,
Vijay,Yadav,vjyaav23@gmail.com,End User,
Vijay,Yadav,vjyaav24@gmail.com,End User,
Vijay,Yadav,vjyaav25@gmail.com,End User,
Vijay,Yadav,vjyaav26@gmail.com,End User,
Vijay,Yadav,vjyaav27@gmail.com,End User,
Vijay,Yadav,vjyaav28@gmail.com,End User,
Vijay,Yadav,vjyaav29@gmail.com,End User,
Vijay,Yadav,vjyaav30@gmail.com,End User,
Vijay,Yadav,vjyaav31@gmail.com,End User,
Vijay,Yadav,vjyaav32@gmail.com,End User,
Vijay,Yadav,vjyaav33@gmail.com,End User,
Vijay,Yadav,vjyaav34@gmail.com,End User,
Vijay,Yadav,vjyaav35@gmail.com,End User,
Vijay,Yadav,vjyaav36@gmail.com,End User,
Vijay,Yadav,vjyaav37@gmail.com,End User,
Vijay,Yadav,vjyaav38@gmail.com,End User,
Vijay,Yadav,vjyaav39@gmail.com,End User,
Vijay,Yadav,vjyaav40@gmail.com,End User,
Vijay,Yadav,vjyaav41@gmail.com,End User,
Vijay,Yadav,vjyaav42@gmail.com,End User,
Vijay,Yadav,vjyaav43@gmail.com,End User,
Vijay,Yadav,vjyaav44@gmail.com,End User,
Vijay,Yadav,vjyaav45@gmail.com,End User,
Vijay,Yadav,vjyaav46@gmail.com,End User,
Vijay,Yadav,vjyaav47@gmail.com,End User,
Vijay,Yadav,vjyaav48@gmail.com,End User,
Vijay,Yadav,vjyaav49@gmail.com,End User,
Vijay,Yadav,vjyaav50@gmail.com,End User,
Vijay,Yadav,vjyaav51@gmail.com,End User,
Vijay,Yadav,vjyaav52@gmail.com,End User,
Vijay,Yadav,vjyaav53@gmail.com,End User,
Vijay,Yadav,vjyaav54@gmail.com,End User,
Vijay,Yadav,vjyaav55@gmail.com,End User,
Vijay,Yadav,vjyaav56@gmail.com,End User,
Vijay,Yadav,vjyaav57@gmail.com,End User,
Vijay,Yadav,vjyaav58@gmail.com,End User,
Vijay,Yadav,vjyaav59@gmail.com,End User,
Vijay,Yadav,vjyaav60@gmail.com,End User,
Vijay,Yadav,vjyaav61@gmail.com,End User,
Vijay,Yadav,vjyaav62@gmail.com,End User,
Vijay,Yadav,vjyaav63@gmail.com,End User,
Vijay,Yadav,vjyaav64@gmail.com,End User,
Vijay,Yadav,vjyaav65@gmail.com,End User,
Vijay,Yadav,vjyaav66@gmail.com,End User,
Vijay,Yadav,vjyaav67@gmail.com,End User,
Vijay,Yadav,vjyaav68@gmail.com,End User,
Vijay,Yadav,vjyaav69@gmail.com,End User,
Vijay,Yadav,vjyaav70@gmail.com,End User,
Vijay,Yadav,vjyaav71@gmail.com,End User,
Vijay,Yadav,vjyaav72@gmail.com,End User,
Vijay,Yadav,vjyaav73@gmail.com,End User,
Vijay,Yadav,vjyaav74@gmail.com,End User,
Vijay,Yadav,vjyaav75@gmail.com,End User,
Vijay,Yadav,vjyaav76@gmail.com,End User,
Vijay,Yadav,vjyaav77@gmail.com,End User,
Vijay,Yadav,vjyaav78@gmail.com,End User,
Vijay,Yadav,vjyaav79@gmail.com,End User,
Vijay,Yadav,vjyaav80@gmail.com,End User,
Vijay,Yadav,vjyaav81@gmail.com,End User,
Vijay,Yadav,vjyaav82@gmail.com,End User,
Vijay,Yadav,vjyaav83@gmail.com,End User,
Vijay,Yadav,vjyaav84@gmail.com,End User,
Vijay,Yadav,vjyaav85@gmail.com,End User,
Vijay,Yadav,vjyaav86@gmail.com,End User,
Vijay,Yadav,vjyaav87@gmail.com,End User,
Vijay,Yadav,vjyaav88@gmail.com,End User,
Vijay,Yadav,vjyaav89@gmail.com,End User,
Vijay,Yadav,vjyaav90@gmail.com,End User,
Vijay,Yadav,vjyaav91@gmail.com,End User,
Vijay,Yadav,vjyaav92@gmail.com,End User,
Vijay,Yadav,vjyaav93@gmail.com,End User,
Vijay,Yadav,vjyaav94@gmail.com,End User,
Vijay,Yadav,vjyaav95@gmail.com,End User,
Vijay,Yadav,vjyaav96@gmail.com,End User,
Vijay,Yadav,vjyaav97@gmail.com,End User,
Vijay,Yadav,vjyaav98@gmail.com,End User,
Vijay,Yadav,vjyaav99@gmail.com,End User,
Vijay,Yadav,vjyaav100@gmail.com,End User,
Vijay,Yadav,vjyaav101@gmail.com,End User,
Vijay,Yadav,vjyaav102@gmail.com,End User,
Vijay,Yadav,vjyaav103@gmail.com,End User,
Vijay,Yadav,vjyaav104@gmail.com,End User,
Vijay,Yadav,vjyaav105@gmail.com,End User,
Vijay,Yadav,vjyaav106@gmail.com,End User,
Vijay,Yadav,vjyaav107@gmail.com,End User,
Vijay,Yadav,vjyaav108@gmail.com,End User,
Vijay,Yadav,vjyaav109@gmail.com,End User,
Vijay,Yadav,vjyaav110@gmail.com,End User,
Vijay,Yadav,vjyaav111@gmail.com,End User,
Vijay,Yadav,vjyaav112@gmail.com,End User,
Vijay,Yadav,vjyaav113@gmail.com,End User,
Vijay,Yadav,vjyaav114@gmail.com,End User,
Vijay,Yadav,vjyaav115@gmail.com,End User,
Vijay,Yadav,vjyaav116@gmail.com,End User,
Vijay,Yadav,vjyaav117@gmail.com,End User,
Vijay,Yadav,vjyaav118@gmail.com,End User,
Vijay,Yadav,vjyaav119@gmail.com,End User,
Vijay,Yadav,vjyaav120@gmail.com,End User,
Vijay,Yadav,vjyaav121@gmail.com,End User,
Vijay,Yadav,vjyaav122@gmail.com,End User,
Vijay,Yadav,vjyaav123@gmail.com,End User,
Vijay,Yadav,vjyaav124@gmail.com,End User,
Vijay,Yadav,vjyaav125@gmail.com,End User,
Vijay,Yadav,vjyaav126@gmail.com,End User,
Vijay,Yadav,vjyaav127@gmail.com,End User,
Vijay,Yadav,vjyaav128@gmail.com,End User,
Vijay,Yadav,vjyaav129@gmail.com,End User,
Vijay,Yadav,vjyaav130@gmail.com,End User,
Vijay,Yadav,vjyaav131@gmail.com,End User,
Vijay,Yadav,vjyaav132@gmail.com,End User,
Vijay,Yadav,vjyaav133@gmail.com,End User,
Vijay,Yadav,vjyaav134@gmail.com,End User,
Vijay,Yadav,vjyaav135@gmail.com,End User,
Vijay,Yadav,vjyaav136@gmail.com,End User,
Vijay,Yadav,vjyaav137@gmail.com,End User,
Vijay,Yadav,vjyaav138@gmail.com,End User,
Vijay,Yadav,vjyaav139@gmail.com,End User,
Vijay,Yadav,vjyaav140@gmail.com,End User,
Vijay,Yadav,vjyaav141@gmail.com,End User,
Vijay,Yadav,vjyaav142@gmail.com,End User,
Vijay,Yadav,vjyaav143@gmail.com,End User,
Vijay,Yadav,vjyaav144@gmail.com,End User,
Vijay,Yadav,vjyaav145@gmail.com,End User,
Vijay,Yadav,vjyaav146@gmail.com,End User,
Vijay,Yadav,vjyaav147@gmail.com,End User,
Vijay,Yadav,vjyaav148@gmail.com,End User,
Vijay,Yadav,vjyaav149@gmail.com,End User,
Vijay,Yadav,vjyaav150@gmail.com,End User,
Vijay,Yadav,vjyaav151@gmail.com,End User,
Vijay,Yadav,vjyaav152@gmail.com,End User,
Vijay,Yadav,vjyaav153@gmail.com,End User,
Vijay,Yadav,vjyaav154@gmail.com,End User,
Vijay,Yadav,vjyaav155@gmail.com,End User,
Vijay,Yadav,vjyaav156@gmail.com,End User,
Vijay,Yadav,vjyaav157@gmail.com,End User,
Vijay,Yadav,vjyaav158@gmail.com,End User,
Vijay,Yadav,vjyaav159@gmail.com,End User,
Vijay,Yadav,vjyaav160@gmail.com,End User,
Vijay,Yadav,vjyaav161@gmail.com,End User,
Vijay,Yadav,vjyaav162@gmail.com,End User,
Vijay,Yadav,vjyaav163@gmail.com,End User,
Vijay,Yadav,vjyaav164@gmail.com,End User,
Vijay,Yadav,vjyaav165@gmail.com,End User,
Vijay,Yadav,vjyaav166@gmail.com,End User,
Vijay,Yadav,vjyaav167@gmail.com,End User,
Vijay,Yadav,vjyaav168@gmail.com,End User,
Vijay,Yadav,vjyaav169@gmail.com,End User,
Vijay,Yadav,vjyaav170@gmail.com,End User,
Vijay,Yadav,vjyaav171@gmail.com,End User,
Vijay,Yadav,vjyaav172@gmail.com,End User,
Vijay,Yadav,vjyaav173@gmail.com,End User,
Vijay,Yadav,vjyaav174@gmail.com,End User,
Vijay,Yadav,vjyaav175@gmail.com,End User,
Vijay,Yadav,vjyaav176@gmail.com,End User,
Vijay,Yadav,vjyaav177@gmail.com,End User,
Vijay,Yadav,vjyaav178@gmail.com,End User,
Vijay,Yadav,vjyaav179@gmail.com,End User,
Vijay,Yadav,vjyaav180@gmail.com,End User,
Vijay,Yadav,vjyaav181@gmail.com,End User,
Vijay,Yadav,vjyaav182@gmail.com,End User,
Vijay,Yadav,vjyaav183@gmail.com,End User,
Vijay,Yadav,vjyaav184@gmail.com,End User,
Vijay,Yadav,vjyaav185@gmail.com,End User,
Vijay,Yadav,vjyaav186@gmail.com,End User,
Vijay,Yadav,vjyaav187@gmail.com,End User,
Vijay,Yadav,vjyaav188@gmail.com,End User,
Vijay,Yadav,vjyaav189@gmail.com,End User,
Vijay,Yadav,vjyaav190@gmail.com,End User,
Vijay,Yadav,vjyaav191@gmail.com,End User,
Vijay,Yadav,vjyaav192@gmail.com,End User,
Vijay,Yadav,vjyaav193@gmail.com,End User,
Vijay,Yadav,vjyaav194@gmail.com,End User,
Vijay,Yadav,vjyaav195@gmail.com,End User,
Vijay,Yadav,vjyaav196@gmail.com,End User,
Vijay,Yadav,vjyaav197@gmail.com,End User,
Vijay,Yadav,vjyaav198@gmail.com,End User,
Vijay,Yadav,vjyaav199@gmail.com,End User,
Vijay,Yadav,vjyaav200@gmail.com,End User,
Vijay,Yadav,vjyaav201@gmail.com,End User,
Vijay,Yadav,vjyaav202@gmail.com,End User,
Vijay,Yadav,vjyaav203@gmail.com,End User,
Vijay,Yadav,vjyaav204@gmail.com,End User,
Vijay,Yadav,vjyaav205@gmail.com,End User,
Vijay,Yadav,vjyaav206@gmail.com,End User,
Vijay,Yadav,vjyaav207@gmail.com,End User,
Vijay,Yadav,vjyaav208@gmail.com,End User,
Vijay,Yadav,vjyaav209@gmail.com,End User,
Vijay,Yadav,vjyaav210@gmail.com,End User,
Vijay,Yadav,vjyaav211@gmail.com,End User,
Vijay,Yadav,vjyaav212@gmail.com,End User,
Vijay,Yadav,vjyaav213@gmail.com,End User,
Vijay,Yadav,vjyaav214@gmail.com,End User,
Vijay,Yadav,vjyaav215@gmail.com,End User,
Vijay,Yadav,vjyaav216@gmail.com,End User,
Vijay,Yadav,vjyaav217@gmail.com,End User,
Vijay,Yadav,vjyaav218@gmail.com,End User,
Vijay,Yadav,vjyaav219@gmail.com,End User,
Vijay,Yadav,vjyaav220@gmail.com,End User,
Vijay,Yadav,vjyaav221@gmail.com,End User,
Vijay,Yadav,vjyaav222@gmail.com,End User,
Vijay,Yadav,vjyaav223@gmail.com,End User,
Vijay,Yadav,vjyaav224@gmail.com,End User,
Vijay,Yadav,vjyaav225@gmail.com,End User,
Vijay,Yadav,vjyaav226@gmail.com,End User,
Vijay,Yadav,vjyaav227@gmail.com,End User,
Vijay,Yadav,vjyaav228@gmail.com,End User,
Vijay,Yadav,vjyaav229@gmail.com,End User,
Vijay,Yadav,vjyaav230@gmail.com,End User,
Vijay,Yadav,vjyaav231@gmail.com,End User,
Vijay,Yadav,vjyaav232@gmail.com,End User,
Vijay,Yadav,vjyaav233@gmail.com,End User,
Vijay,Yadav,vjyaav234@gmail.com,End User,
Vijay,Yadav,vjyaav235@gmail.com,End User,
Vijay,Yadav,vjyaav236@gmail.com,End User,
Vijay,Yadav,vjyaav237@gmail.com,End User,
Vijay,Yadav,vjyaav238@gmail.com,End User,
Vijay,Yadav,vjyaav239@gmail.com,End User,
Vijay,Yadav,vjyaav240@gmail.com,End User,
Vijay,Yadav,vjyaav241@gmail.com,End User,
Vijay,Yadav,vjyaav242@gmail.com,End User,
Vijay,Yadav,vjyaav243@gmail.com,End User,
Vijay,Yadav,vjyaav244@gmail.com,End User,
Vijay,Yadav,vjyaav245@gmail.com,End User,
Vijay,Yadav,vjyaav246@gmail.com,End User,
Vijay,Yadav,vjyaav247@gmail.com,End User,
Vijay,Yadav,vjyaav248@gmail.com,End User,
Vijay,Yadav,vjyaav249@gmail.com,End User,
Vijay,Yadav,vjyaav250@gmail.com,End User,
Vijay,Yadav,vjyaav251@gmail.com,End User,
1 First Name Last Name Email Groups User Role Group
2 Vijay Yadav vjyaav12@gmail.com vjyaav1@gmail.com All Users|Admin Admin
3 Vijay Yadav vjyaav13@gmail.com vjyaav2@gmail.com All Users Builder
4 Vijay Yadav vjyaav14@gmail.com vjyaav3@gmail.com All Users Builder
5 Vijay Yadav vjyaav15@gmail.com vjyaav4@gmail.com All Users End User
6 Vijay Yadav vjyaav16@gmail.com vjyaav5@gmail.com All Users End User
7 Vijay Yadav vjyaav17@gmail.com vjyaav6@gmail.com All Users End User
8 Vijay Yadav vjyaav18@gmail.com vjyaav7@gmail.com All Users End User
9 Vijay Yadav vjyaav19@gmail.com vjyaav8@gmail.com All Users End User
10 Vijay Yadav vjyaav20@gmail.com vjyaav9@gmail.com All Users End User
11 Vijay Yadav vjyaav21@gmail.com vjyaav10@gmail.com All Users End User
12 Vijay Yadav vjyaav22@gmail.com vjyaav11@gmail.com All Users End User
13 Vijay Yadav vjyaav23@gmail.com vjyaav12@gmail.com All Users End User
14 Vijay Yadav vjyaav24@gmail.com vjyaav13@gmail.com All Users End User
15 Vijay Yadav vjyaav25@gmail.com vjyaav14@gmail.com All Users End User
16 Vijay Yadav vjyaav26@gmail.com vjyaav15@gmail.com All Users End User
17 Vijay Yadav vjyaav27@gmail.com vjyaav16@gmail.com All Users End User
18 Vijay Yadav vjyaav28@gmail.com vjyaav17@gmail.com All Users End User
19 Vijay Yadav vjyaav29@gmail.com vjyaav18@gmail.com All Users End User
20 Vijay Yadav vjyaav30@gmail.com vjyaav19@gmail.com All Users End User
21 Vijay Yadav vjyaav31@gmail.com vjyaav20@gmail.com All Users End User
22 Vijay Yadav vjyaav32@gmail.com vjyaav21@gmail.com All Users End User
23 Vijay Yadav vjyaav33@gmail.com vjyaav22@gmail.com All Users End User
24 Vijay Yadav vjyaav34@gmail.com vjyaav23@gmail.com All Users End User
25 Vijay Yadav vjyaav35@gmail.com vjyaav24@gmail.com All Users End User
26 Vijay Yadav vjyaav36@gmail.com vjyaav25@gmail.com All Users End User
27 Vijay Yadav vjyaav37@gmail.com vjyaav26@gmail.com All Users End User
28 Vijay Yadav vjyaav38@gmail.com vjyaav27@gmail.com All Users End User
29 Vijay Yadav vjyaav39@gmail.com vjyaav28@gmail.com All Users End User
30 Vijay Yadav vjyaav40@gmail.com vjyaav29@gmail.com All Users End User
31 Vijay Yadav vjyaav41@gmail.com vjyaav30@gmail.com All Users End User
32 Vijay Yadav vjyaav42@gmail.com vjyaav31@gmail.com All Users End User
33 Vijay Yadav vjyaav43@gmail.com vjyaav32@gmail.com All Users End User
34 Vijay Yadav vjyaav44@gmail.com vjyaav33@gmail.com All Users End User
35 Vijay Yadav vjyaav45@gmail.com vjyaav34@gmail.com All Users End User
36 Vijay Yadav vjyaav46@gmail.com vjyaav35@gmail.com All Users End User
37 Vijay Yadav vjyaav47@gmail.com vjyaav36@gmail.com All Users End User
38 Vijay Yadav vjyaav48@gmail.com vjyaav37@gmail.com All Users End User
39 Vijay Yadav vjyaav49@gmail.com vjyaav38@gmail.com All Users End User
40 Vijay Yadav vjyaav50@gmail.com vjyaav39@gmail.com All Users End User
41 Vijay Yadav vjyaav51@gmail.com vjyaav40@gmail.com All Users End User
42 Vijay Yadav vjyaav52@gmail.com vjyaav41@gmail.com All Users End User
43 Vijay Yadav vjyaav53@gmail.com vjyaav42@gmail.com All Users End User
44 Vijay Yadav vjyaav54@gmail.com vjyaav43@gmail.com All Users End User
45 Vijay Yadav vjyaav55@gmail.com vjyaav44@gmail.com All Users End User
46 Vijay Yadav vjyaav56@gmail.com vjyaav45@gmail.com All Users End User
47 Vijay Yadav vjyaav57@gmail.com vjyaav46@gmail.com All Users End User
48 Vijay Yadav vjyaav58@gmail.com vjyaav47@gmail.com All Users End User
49 Vijay Yadav vjyaav59@gmail.com vjyaav48@gmail.com All Users End User
50 Vijay Yadav vjyaav60@gmail.com vjyaav49@gmail.com All Users End User
51 Vijay Yadav vjyaav61@gmail.com vjyaav50@gmail.com All Users End User
52 Vijay Yadav vjyaav62@gmail.com vjyaav51@gmail.com All Users End User
53 Vijay Yadav vjyaav63@gmail.com vjyaav52@gmail.com All Users End User
54 Vijay Yadav vjyaav64@gmail.com vjyaav53@gmail.com All Users End User
55 Vijay Yadav vjyaav65@gmail.com vjyaav54@gmail.com All Users End User
56 Vijay Yadav vjyaav66@gmail.com vjyaav55@gmail.com All Users End User
57 Vijay Yadav vjyaav67@gmail.com vjyaav56@gmail.com All Users End User
58 Vijay Yadav vjyaav68@gmail.com vjyaav57@gmail.com All Users End User
59 Vijay Yadav vjyaav69@gmail.com vjyaav58@gmail.com All Users End User
60 Vijay Yadav vjyaav70@gmail.com vjyaav59@gmail.com All Users End User
61 Vijay Yadav vjyaav71@gmail.com vjyaav60@gmail.com All Users End User
62 Vijay Yadav vjyaav72@gmail.com vjyaav61@gmail.com All Users End User
63 Vijay Yadav vjyaav73@gmail.com vjyaav62@gmail.com All Users End User
64 Vijay Yadav vjyaav74@gmail.com vjyaav63@gmail.com All Users End User
65 Vijay Yadav vjyaav75@gmail.com vjyaav64@gmail.com All Users End User
66 Vijay Yadav vjyaav76@gmail.com vjyaav65@gmail.com All Users End User
67 Vijay Yadav vjyaav77@gmail.com vjyaav66@gmail.com All Users End User
68 Vijay Yadav vjyaav78@gmail.com vjyaav67@gmail.com All Users End User
69 Vijay Yadav vjyaav79@gmail.com vjyaav68@gmail.com All Users End User
70 Vijay Yadav vjyaav80@gmail.com vjyaav69@gmail.com All Users End User
71 Vijay Yadav vjyaav81@gmail.com vjyaav70@gmail.com All Users End User
72 Vijay Yadav vjyaav82@gmail.com vjyaav71@gmail.com All Users End User
73 Vijay Yadav vjyaav83@gmail.com vjyaav72@gmail.com All Users End User
74 Vijay Yadav vjyaav84@gmail.com vjyaav73@gmail.com All Users End User
75 Vijay Yadav vjyaav85@gmail.com vjyaav74@gmail.com All Users End User
76 Vijay Yadav vjyaav86@gmail.com vjyaav75@gmail.com All Users End User
77 Vijay Yadav vjyaav87@gmail.com vjyaav76@gmail.com All Users End User
78 Vijay Yadav vjyaav88@gmail.com vjyaav77@gmail.com All Users End User
79 Vijay Yadav vjyaav89@gmail.com vjyaav78@gmail.com All Users End User
80 Vijay Yadav vjyaav90@gmail.com vjyaav79@gmail.com All Users End User
81 Vijay Yadav vjyaav91@gmail.com vjyaav80@gmail.com All Users End User
82 Vijay Yadav vjyaav92@gmail.com vjyaav81@gmail.com All Users End User
83 Vijay Yadav vjyaav93@gmail.com vjyaav82@gmail.com All Users End User
84 Vijay Yadav vjyaav94@gmail.com vjyaav83@gmail.com All Users End User
85 Vijay Yadav vjyaav95@gmail.com vjyaav84@gmail.com All Users End User
86 Vijay Yadav vjyaav96@gmail.com vjyaav85@gmail.com All Users End User
87 Vijay Yadav vjyaav97@gmail.com vjyaav86@gmail.com All Users End User
88 Vijay Yadav vjyaav98@gmail.com vjyaav87@gmail.com All Users End User
89 Vijay Yadav vjyaav99@gmail.com vjyaav88@gmail.com All Users End User
90 Vijay Yadav vjyaav100@gmail.com vjyaav89@gmail.com All Users End User
91 Vijay Yadav vjyaav101@gmail.com vjyaav90@gmail.com All Users End User
92 Vijay Yadav vjyaav102@gmail.com vjyaav91@gmail.com All Users End User
93 Vijay Yadav vjyaav103@gmail.com vjyaav92@gmail.com All Users End User
94 Vijay Yadav vjyaav104@gmail.com vjyaav93@gmail.com All Users End User
95 Vijay Yadav vjyaav105@gmail.com vjyaav94@gmail.com All Users End User
96 Vijay Yadav vjyaav106@gmail.com vjyaav95@gmail.com All Users End User
97 Vijay Yadav vjyaav107@gmail.com vjyaav96@gmail.com All Users End User
98 Vijay Yadav vjyaav108@gmail.com vjyaav97@gmail.com All Users End User
99 Vijay Yadav vjyaav109@gmail.com vjyaav98@gmail.com All Users End User
100 Vijay Yadav vjyaav110@gmail.com vjyaav99@gmail.com All Users End User
101 Vijay Yadav vjyaav111@gmail.com vjyaav100@gmail.com All Users End User
102 Vijay Yadav vjyaav112@gmail.com vjyaav101@gmail.com All Users End User
103 Vijay Yadav vjyaav113@gmail.com vjyaav102@gmail.com All Users End User
104 Vijay Yadav vjyaav114@gmail.com vjyaav103@gmail.com All Users End User
105 Vijay Yadav vjyaav115@gmail.com vjyaav104@gmail.com All Users End User
106 Vijay Yadav vjyaav116@gmail.com vjyaav105@gmail.com All Users End User
107 Vijay Yadav vjyaav117@gmail.com vjyaav106@gmail.com All Users End User
108 Vijay Yadav vjyaav118@gmail.com vjyaav107@gmail.com All Users End User
109 Vijay Yadav vjyaav119@gmail.com vjyaav108@gmail.com All Users End User
110 Vijay Yadav vjyaav120@gmail.com vjyaav109@gmail.com All Users End User
111 Vijay Yadav vjyaav121@gmail.com vjyaav110@gmail.com All Users End User
112 Vijay Yadav vjyaav122@gmail.com vjyaav111@gmail.com All Users End User
113 Vijay Yadav vjyaav123@gmail.com vjyaav112@gmail.com All Users End User
114 Vijay Yadav vjyaav124@gmail.com vjyaav113@gmail.com All Users End User
115 Vijay Yadav vjyaav125@gmail.com vjyaav114@gmail.com All Users End User
116 Vijay Yadav vjyaav126@gmail.com vjyaav115@gmail.com All Users End User
117 Vijay Yadav vjyaav127@gmail.com vjyaav116@gmail.com All Users End User
118 Vijay Yadav vjyaav128@gmail.com vjyaav117@gmail.com All Users End User
119 Vijay Yadav vjyaav129@gmail.com vjyaav118@gmail.com All Users End User
120 Vijay Yadav vjyaav130@gmail.com vjyaav119@gmail.com All Users End User
121 Vijay Yadav vjyaav131@gmail.com vjyaav120@gmail.com All Users End User
122 Vijay Yadav vjyaav132@gmail.com vjyaav121@gmail.com All Users End User
123 Vijay Yadav vjyaav133@gmail.com vjyaav122@gmail.com All Users End User
124 Vijay Yadav vjyaav134@gmail.com vjyaav123@gmail.com All Users End User
125 Vijay Yadav vjyaav135@gmail.com vjyaav124@gmail.com All Users End User
126 Vijay Yadav vjyaav136@gmail.com vjyaav125@gmail.com All Users End User
127 Vijay Yadav vjyaav137@gmail.com vjyaav126@gmail.com All Users End User
128 Vijay Yadav vjyaav138@gmail.com vjyaav127@gmail.com All Users End User
129 Vijay Yadav vjyaav139@gmail.com vjyaav128@gmail.com All Users End User
130 Vijay Yadav vjyaav140@gmail.com vjyaav129@gmail.com All Users End User
131 Vijay Yadav vjyaav141@gmail.com vjyaav130@gmail.com All Users End User
132 Vijay Yadav vjyaav142@gmail.com vjyaav131@gmail.com All Users End User
133 Vijay Yadav vjyaav143@gmail.com vjyaav132@gmail.com All Users End User
134 Vijay Yadav vjyaav144@gmail.com vjyaav133@gmail.com All Users End User
135 Vijay Yadav vjyaav145@gmail.com vjyaav134@gmail.com All Users End User
136 Vijay Yadav vjyaav146@gmail.com vjyaav135@gmail.com All Users End User
137 Vijay Yadav vjyaav147@gmail.com vjyaav136@gmail.com All Users End User
138 Vijay Yadav vjyaav148@gmail.com vjyaav137@gmail.com All Users End User
139 Vijay Yadav vjyaav149@gmail.com vjyaav138@gmail.com All Users End User
140 Vijay Yadav vjyaav150@gmail.com vjyaav139@gmail.com All Users End User
141 Vijay Yadav vjyaav151@gmail.com vjyaav140@gmail.com All Users End User
142 Vijay Yadav vjyaav152@gmail.com vjyaav141@gmail.com All Users End User
143 Vijay Yadav vjyaav153@gmail.com vjyaav142@gmail.com All Users End User
144 Vijay Yadav vjyaav154@gmail.com vjyaav143@gmail.com All Users End User
145 Vijay Yadav vjyaav155@gmail.com vjyaav144@gmail.com All Users End User
146 Vijay Yadav vjyaav156@gmail.com vjyaav145@gmail.com All Users End User
147 Vijay Yadav vjyaav157@gmail.com vjyaav146@gmail.com All Users End User
148 Vijay Yadav vjyaav158@gmail.com vjyaav147@gmail.com All Users End User
149 Vijay Yadav vjyaav159@gmail.com vjyaav148@gmail.com All Users End User
150 Vijay Yadav vjyaav160@gmail.com vjyaav149@gmail.com All Users End User
151 Vijay Yadav vjyaav161@gmail.com vjyaav150@gmail.com All Users End User
152 Vijay Yadav vjyaav162@gmail.com vjyaav151@gmail.com All Users End User
153 Vijay Yadav vjyaav163@gmail.com vjyaav152@gmail.com All Users End User
154 Vijay Yadav vjyaav164@gmail.com vjyaav153@gmail.com All Users End User
155 Vijay Yadav vjyaav165@gmail.com vjyaav154@gmail.com All Users End User
156 Vijay Yadav vjyaav166@gmail.com vjyaav155@gmail.com All Users End User
157 Vijay Yadav vjyaav167@gmail.com vjyaav156@gmail.com All Users End User
158 Vijay Yadav vjyaav168@gmail.com vjyaav157@gmail.com All Users End User
159 Vijay Yadav vjyaav169@gmail.com vjyaav158@gmail.com All Users End User
160 Vijay Yadav vjyaav170@gmail.com vjyaav159@gmail.com All Users End User
161 Vijay Yadav vjyaav171@gmail.com vjyaav160@gmail.com All Users End User
162 Vijay Yadav vjyaav172@gmail.com vjyaav161@gmail.com All Users End User
163 Vijay Yadav vjyaav173@gmail.com vjyaav162@gmail.com All Users End User
164 Vijay Yadav vjyaav174@gmail.com vjyaav163@gmail.com All Users End User
165 Vijay Yadav vjyaav175@gmail.com vjyaav164@gmail.com All Users End User
166 Vijay Yadav vjyaav176@gmail.com vjyaav165@gmail.com All Users End User
167 Vijay Yadav vjyaav177@gmail.com vjyaav166@gmail.com All Users End User
168 Vijay Yadav vjyaav178@gmail.com vjyaav167@gmail.com All Users End User
169 Vijay Yadav vjyaav179@gmail.com vjyaav168@gmail.com All Users End User
170 Vijay Yadav vjyaav180@gmail.com vjyaav169@gmail.com All Users End User
171 Vijay Yadav vjyaav181@gmail.com vjyaav170@gmail.com All Users End User
172 Vijay Yadav vjyaav182@gmail.com vjyaav171@gmail.com All Users End User
173 Vijay Yadav vjyaav183@gmail.com vjyaav172@gmail.com All Users End User
174 Vijay Yadav vjyaav184@gmail.com vjyaav173@gmail.com All Users End User
175 Vijay Yadav vjyaav185@gmail.com vjyaav174@gmail.com All Users End User
176 Vijay Yadav vjyaav186@gmail.com vjyaav175@gmail.com All Users End User
177 Vijay Yadav vjyaav187@gmail.com vjyaav176@gmail.com All Users End User
178 Vijay Yadav vjyaav188@gmail.com vjyaav177@gmail.com All Users End User
179 Vijay Yadav vjyaav189@gmail.com vjyaav178@gmail.com All Users End User
180 Vijay Yadav vjyaav190@gmail.com vjyaav179@gmail.com All Users End User
181 Vijay Yadav vjyaav191@gmail.com vjyaav180@gmail.com All Users End User
182 Vijay Yadav vjyaav192@gmail.com vjyaav181@gmail.com All Users End User
183 Vijay Yadav vjyaav193@gmail.com vjyaav182@gmail.com All Users End User
184 Vijay Yadav vjyaav194@gmail.com vjyaav183@gmail.com All Users End User
185 Vijay Yadav vjyaav195@gmail.com vjyaav184@gmail.com All Users End User
186 Vijay Yadav vjyaav196@gmail.com vjyaav185@gmail.com All Users End User
187 Vijay Yadav vjyaav197@gmail.com vjyaav186@gmail.com All Users End User
188 Vijay Yadav vjyaav198@gmail.com vjyaav187@gmail.com All Users End User
189 Vijay Yadav vjyaav199@gmail.com vjyaav188@gmail.com All Users End User
190 Vijay Yadav vjyaav200@gmail.com vjyaav189@gmail.com All Users End User
191 Vijay Yadav vjyaav201@gmail.com vjyaav190@gmail.com All Users End User
192 Vijay Yadav vjyaav202@gmail.com vjyaav191@gmail.com All Users End User
193 Vijay Yadav vjyaav203@gmail.com vjyaav192@gmail.com All Users End User
194 Vijay Yadav vjyaav204@gmail.com vjyaav193@gmail.com All Users End User
195 Vijay Yadav vjyaav205@gmail.com vjyaav194@gmail.com All Users End User
196 Vijay Yadav vjyaav206@gmail.com vjyaav195@gmail.com All Users End User
197 Vijay Yadav vjyaav207@gmail.com vjyaav196@gmail.com All Users End User
198 Vijay Yadav vjyaav208@gmail.com vjyaav197@gmail.com All Users End User
199 Vijay Yadav vjyaav209@gmail.com vjyaav198@gmail.com All Users End User
200 Vijay Yadav vjyaav210@gmail.com vjyaav199@gmail.com All Users End User
201 Vijay Yadav vjyaav211@gmail.com vjyaav200@gmail.com All Users End User
202 Vijay Yadav vjyaav212@gmail.com vjyaav201@gmail.com All Users End User
203 Vijay Yadav vjyaav213@gmail.com vjyaav202@gmail.com All Users End User
204 Vijay Yadav vjyaav214@gmail.com vjyaav203@gmail.com All Users End User
205 Vijay Yadav vjyaav215@gmail.com vjyaav204@gmail.com All Users End User
206 Vijay Yadav vjyaav216@gmail.com vjyaav205@gmail.com All Users End User
207 Vijay Yadav vjyaav217@gmail.com vjyaav206@gmail.com All Users End User
208 Vijay Yadav vjyaav218@gmail.com vjyaav207@gmail.com All Users End User
209 Vijay Yadav vjyaav219@gmail.com vjyaav208@gmail.com All Users End User
210 Vijay Yadav vjyaav220@gmail.com vjyaav209@gmail.com All Users End User
211 Vijay Yadav vjyaav221@gmail.com vjyaav210@gmail.com All Users End User
212 Vijay Yadav vjyaav222@gmail.com vjyaav211@gmail.com All Users End User
213 Vijay Yadav vjyaav223@gmail.com vjyaav212@gmail.com All Users End User
214 Vijay Yadav vjyaav224@gmail.com vjyaav213@gmail.com All Users End User
215 Vijay Yadav vjyaav225@gmail.com vjyaav214@gmail.com All Users End User
216 Vijay Yadav vjyaav226@gmail.com vjyaav215@gmail.com All Users End User
217 Vijay Yadav vjyaav227@gmail.com vjyaav216@gmail.com All Users End User
218 Vijay Yadav vjyaav228@gmail.com vjyaav217@gmail.com All Users End User
219 Vijay Yadav vjyaav229@gmail.com vjyaav218@gmail.com All Users End User
220 Vijay Yadav vjyaav230@gmail.com vjyaav219@gmail.com All Users End User
221 Vijay Yadav vjyaav231@gmail.com vjyaav220@gmail.com All Users End User
222 Vijay Yadav vjyaav232@gmail.com vjyaav221@gmail.com All Users End User
223 Vijay Yadav vjyaav233@gmail.com vjyaav222@gmail.com All Users End User
224 Vijay Yadav vjyaav234@gmail.com vjyaav223@gmail.com All Users End User
225 Vijay Yadav vjyaav235@gmail.com vjyaav224@gmail.com All Users End User
226 Vijay Yadav vjyaav236@gmail.com vjyaav225@gmail.com All Users End User
227 Vijay Yadav vjyaav237@gmail.com vjyaav226@gmail.com All Users End User
228 Vijay Yadav vjyaav238@gmail.com vjyaav227@gmail.com All Users End User
229 Vijay Yadav vjyaav239@gmail.com vjyaav228@gmail.com All Users End User
230 Vijay Yadav vjyaav240@gmail.com vjyaav229@gmail.com All Users End User
231 Vijay Yadav vjyaav241@gmail.com vjyaav230@gmail.com All Users End User
232 Vijay Yadav vjyaav242@gmail.com vjyaav231@gmail.com All Users End User
233 Vijay Yadav vjyaav243@gmail.com vjyaav232@gmail.com All Users End User
234 Vijay Yadav vjyaav244@gmail.com vjyaav233@gmail.com All Users End User
235 Vijay Yadav vjyaav245@gmail.com vjyaav234@gmail.com All Users End User
236 Vijay Yadav vjyaav246@gmail.com vjyaav235@gmail.com All Users End User
237 Vijay Yadav vjyaav247@gmail.com vjyaav236@gmail.com All Users End User
238 Vijay Yadav vjyaav248@gmail.com vjyaav237@gmail.com All Users End User
239 Vijay Yadav vjyaav249@gmail.com vjyaav238@gmail.com All Users End User
240 Vijay Yadav vjyaav250@gmail.com vjyaav239@gmail.com All Users End User
241 Vijay Yadav vjyaav251@gmail.com vjyaav240@gmail.com All Users End User
242 Vijay Yadav vjyaav252@gmail.com vjyaav241@gmail.com All Users End User
243 Vijay Yadav vjyaav253@gmail.com vjyaav242@gmail.com All Users End User
244 Vijay Yadav vjyaav254@gmail.com vjyaav243@gmail.com All Users End User
245 Vijay Yadav vjyaav255@gmail.com vjyaav244@gmail.com All Users End User
246 Vijay Yadav vjyaav256@gmail.com vjyaav245@gmail.com All Users End User
247 Vijay Yadav vjyaav257@gmail.com vjyaav246@gmail.com All Users End User
248 Vijay Yadav vjyaav258@gmail.com vjyaav247@gmail.com All Users End User
249 Vijay Yadav vjyaav259@gmail.com vjyaav248@gmail.com All Users End User
250 Vijay Yadav vjyaav260@gmail.com vjyaav249@gmail.com All Users End User
251 Vijay Yadav vjyaav261@gmail.com vjyaav250@gmail.com All Users End User
252 Vijay Yadav vjyaav262@gmail.com vjyaav251@gmail.com All Users End User
Vijay Yadav vjyaav263@gmail.com All Users
Vijay Yadav vjyaav264@gmail.com All Users
Vijay Yadav vjyaav265@gmail.com All Users
Vijay Yadav vjyaav266@gmail.com All Users
Vijay Yadav vjyaav267@gmail.com All Users
Vijay Yadav vjyaav268@gmail.com All Users
Vijay Yadav vjyaav269@gmail.com All Users
Vijay Yadav vjyaav270@gmail.com All Users
Vijay Yadav vjyaav271@gmail.com All Users
Vijay Yadav vjyaav272@gmail.com All Users
Vijay Yadav vjyaav273@gmail.com All Users
Vijay Yadav vjyaav274@gmail.com All Users
Vijay Yadav vjyaav275@gmail.com All Users
Vijay Yadav vjyaav276@gmail.com All Users
Vijay Yadav vjyaav277@gmail.com All Users
Vijay Yadav vjyaav278@gmail.com All Users
Vijay Yadav vjyaav279@gmail.com All Users
Vijay Yadav vjyaav280@gmail.com All Users
Vijay Yadav vjyaav281@gmail.com All Users
Vijay Yadav vjyaav282@gmail.com All Users
Vijay Yadav vjyaav283@gmail.com All Users
Vijay Yadav vjyaav284@gmail.com All Users
Vijay Yadav vjyaav285@gmail.com All Users
Vijay Yadav vjyaav286@gmail.com All Users
Vijay Yadav vjyaav287@gmail.com All Users
Vijay Yadav vjyaav288@gmail.com All Users
Vijay Yadav vjyaav289@gmail.com All Users
Vijay Yadav vjyaav290@gmail.com All Users
Vijay Yadav vjyaav291@gmail.com All Users
Vijay Yadav vjyaav292@gmail.com All Users
Vijay Yadav vjyaav293@gmail.com All Users
Vijay Yadav vjyaav294@gmail.com All Users
Vijay Yadav vjyaav295@gmail.com All Users
Vijay Yadav vjyaav296@gmail.com All Users
Vijay Yadav vjyaav297@gmail.com All Users
Vijay Yadav vjyaav298@gmail.com All Users
Vijay Yadav vjyaav299@gmail.com All Users
Vijay Yadav vjyaav300@gmail.com All Users
Vijay Yadav vjyaav301@gmail.com All Users
Vijay Yadav vjyaav302@gmail.com All Users
Vijay Yadav vjyaav303@gmail.com All Users
Vijay Yadav vjyaav304@gmail.com All Users
Vijay Yadav vjyaav305@gmail.com All Users
Vijay Yadav vjyaav306@gmail.com All Users
Vijay Yadav vjyaav307@gmail.com All Users
Vijay Yadav vjyaav308@gmail.com All Users
Vijay Yadav vjyaav309@gmail.com All Users
Vijay Yadav vjyaav310@gmail.com All Users
Vijay Yadav vjyaav311@gmail.com All Users
Vijay Yadav vjyaav312@gmail.com All Users
Vijay Yadav vjyaav313@gmail.com All Users
Vijay Yadav vjyaav314@gmail.com All Users
Vijay Yadav vjyaav315@gmail.com All Users
Vijay Yadav vjyaav316@gmail.com All Users
Vijay Yadav vjyaav317@gmail.com All Users
Vijay Yadav vjyaav318@gmail.com All Users
Vijay Yadav vjyaav319@gmail.com All Users
Vijay Yadav vjyaav320@gmail.com All Users
Vijay Yadav vjyaav321@gmail.com All Users
Vijay Yadav vjyaav322@gmail.com All Users
Vijay Yadav vjyaav323@gmail.com All Users
Vijay Yadav vjyaav324@gmail.com All Users
Vijay Yadav vjyaav325@gmail.com All Users
Vijay Yadav vjyaav326@gmail.com All Users
Vijay Yadav vjyaav327@gmail.com All Users
Vijay Yadav vjyaav328@gmail.com All Users
Vijay Yadav vjyaav329@gmail.com All Users
Vijay Yadav vjyaav330@gmail.com All Users
Vijay Yadav vjyaav331@gmail.com All Users
Vijay Yadav vjyaav332@gmail.com All Users
Vijay Yadav vjyaav333@gmail.com All Users
Vijay Yadav vjyaav334@gmail.com All Users
Vijay Yadav vjyaav335@gmail.com All Users
Vijay Yadav vjyaav336@gmail.com All Users
Vijay Yadav vjyaav337@gmail.com All Users
Vijay Yadav vjyaav338@gmail.com All Users
Vijay Yadav vjyaav339@gmail.com All Users
Vijay Yadav vjyaav340@gmail.com All Users
Vijay Yadav vjyaav341@gmail.com All Users
Vijay Yadav vjyaav342@gmail.com All Users
Vijay Yadav vjyaav343@gmail.com All Users
Vijay Yadav vjyaav344@gmail.com All Users
Vijay Yadav vjyaav345@gmail.com All Users
Vijay Yadav vjyaav346@gmail.com All Users
Vijay Yadav vjyaav347@gmail.com All Users
Vijay Yadav vjyaav348@gmail.com All Users
Vijay Yadav vjyaav349@gmail.com All Users
Vijay Yadav vjyaav350@gmail.com All Users
Vijay Yadav vjyaav351@gmail.com All Users
Vijay Yadav vjyaav352@gmail.com All Users
Vijay Yadav vjyaav353@gmail.com All Users
Vijay Yadav vjyaav354@gmail.com All Users
Vijay Yadav vjyaav355@gmail.com All Users
Vijay Yadav vjyaav356@gmail.com All Users
Vijay Yadav vjyaav357@gmail.com All Users
Vijay Yadav vjyaav358@gmail.com All Users
Vijay Yadav vjyaav359@gmail.com All Users
Vijay Yadav vjyaav360@gmail.com All Users
Vijay Yadav vjyaav361@gmail.com All Users
Vijay Yadav vjyaav362@gmail.com All Users
Vijay Yadav vjyaav363@gmail.com All Users
Vijay Yadav vjyaav364@gmail.com All Users
Vijay Yadav vjyaav365@gmail.com All Users
Vijay Yadav vjyaav366@gmail.com All Users
Vijay Yadav vjyaav367@gmail.com All Users
Vijay Yadav vjyaav368@gmail.com All Users
Vijay Yadav vjyaav369@gmail.com All Users
Vijay Yadav vjyaav370@gmail.com All Users
Vijay Yadav vjyaav371@gmail.com All Users
Vijay Yadav vjyaav372@gmail.com All Users
Vijay Yadav vjyaav373@gmail.com All Users
Vijay Yadav vjyaav374@gmail.com All Users
Vijay Yadav vjyaav375@gmail.com All Users
Vijay Yadav vjyaav376@gmail.com All Users
Vijay Yadav vjyaav377@gmail.com All Users
Vijay Yadav vjyaav378@gmail.com All Users
Vijay Yadav vjyaav379@gmail.com All Users
Vijay Yadav vjyaav380@gmail.com All Users
Vijay Yadav vjyaav381@gmail.com All Users
Vijay Yadav vjyaav382@gmail.com All Users
Vijay Yadav vjyaav383@gmail.com All Users
Vijay Yadav vjyaav384@gmail.com All Users
Vijay Yadav vjyaav385@gmail.com All Users
Vijay Yadav vjyaav386@gmail.com All Users
Vijay Yadav vjyaav387@gmail.com All Users
Vijay Yadav vjyaav388@gmail.com All Users
Vijay Yadav vjyaav389@gmail.com All Users
Vijay Yadav vjyaav390@gmail.com All Users
Vijay Yadav vjyaav391@gmail.com All Users
Vijay Yadav vjyaav392@gmail.com All Users
Vijay Yadav vjyaav393@gmail.com All Users
Vijay Yadav vjyaav394@gmail.com All Users
Vijay Yadav vjyaav395@gmail.com All Users
Vijay Yadav vjyaav396@gmail.com All Users
Vijay Yadav vjyaav397@gmail.com All Users
Vijay Yadav vjyaav398@gmail.com All Users
Vijay Yadav vjyaav399@gmail.com All Users
Vijay Yadav vjyaav400@gmail.com All Users
Vijay Yadav vjyaav401@gmail.com All Users
Vijay Yadav vjyaav402@gmail.com All Users
Vijay Yadav vjyaav403@gmail.com All Users
Vijay Yadav vjyaav404@gmail.com All Users
Vijay Yadav vjyaav405@gmail.com All Users
Vijay Yadav vjyaav406@gmail.com All Users
Vijay Yadav vjyaav407@gmail.com All Users
Vijay Yadav vjyaav408@gmail.com All Users
Vijay Yadav vjyaav409@gmail.com All Users
Vijay Yadav vjyaav410@gmail.com All Users
Vijay Yadav vjyaav411@gmail.com All Users
Vijay Yadav vjyaav412@gmail.com All Users
Vijay Yadav vjyaav413@gmail.com All Users
Vijay Yadav vjyaav414@gmail.com All Users
Vijay Yadav vjyaav415@gmail.com All Users
Vijay Yadav vjyaav416@gmail.com All Users
Vijay Yadav vjyaav417@gmail.com All Users
Vijay Yadav vjyaav418@gmail.com All Users
Vijay Yadav vjyaav419@gmail.com All Users
Vijay Yadav vjyaav420@gmail.com All Users
Vijay Yadav vjyaav421@gmail.com All Users
Vijay Yadav vjyaav422@gmail.com All Users
Vijay Yadav vjyaav423@gmail.com All Users
Vijay Yadav vjyaav424@gmail.com All Users
Vijay Yadav vjyaav425@gmail.com All Users
Vijay Yadav vjyaav426@gmail.com All Users
Vijay Yadav vjyaav427@gmail.com All Users
Vijay Yadav vjyaav428@gmail.com All Users
Vijay Yadav vjyaav429@gmail.com All Users
Vijay Yadav vjyaav430@gmail.com All Users
Vijay Yadav vjyaav431@gmail.com All Users
Vijay Yadav vjyaav432@gmail.com All Users
Vijay Yadav vjyaav433@gmail.com All Users
Vijay Yadav vjyaav434@gmail.com All Users
Vijay Yadav vjyaav435@gmail.com All Users
Vijay Yadav vjyaav436@gmail.com All Users
Vijay Yadav vjyaav437@gmail.com All Users
Vijay Yadav vjyaav438@gmail.com All Users
Vijay Yadav vjyaav439@gmail.com All Users
Vijay Yadav vjyaav440@gmail.com All Users
Vijay Yadav vjyaav441@gmail.com All Users
Vijay Yadav vjyaav442@gmail.com All Users
Vijay Yadav vjyaav443@gmail.com All Users
Vijay Yadav vjyaav444@gmail.com All Users
Vijay Yadav vjyaav445@gmail.com All Users
Vijay Yadav vjyaav446@gmail.com All Users
Vijay Yadav vjyaav447@gmail.com All Users
Vijay Yadav vjyaav448@gmail.com All Users
Vijay Yadav vjyaav449@gmail.com All Users
Vijay Yadav vjyaav450@gmail.com All Users
Vijay Yadav vjyaav451@gmail.com All Users
Vijay Yadav vjyaav452@gmail.com All Users
Vijay Yadav vjyaav453@gmail.com All Users
Vijay Yadav vjyaav454@gmail.com All Users
Vijay Yadav vjyaav455@gmail.com All Users
Vijay Yadav vjyaav456@gmail.com All Users
Vijay Yadav vjyaav457@gmail.com All Users
Vijay Yadav vjyaav458@gmail.com All Users
Vijay Yadav vjyaav459@gmail.com All Users
Vijay Yadav vjyaav460@gmail.com All Users
Vijay Yadav vjyaav461@gmail.com All Users
Vijay Yadav vjyaav462@gmail.com All Users
Vijay Yadav vjyaav463@gmail.com All Users
Vijay Yadav vjyaav464@gmail.com All Users
Vijay Yadav vjyaav465@gmail.com All Users
Vijay Yadav vjyaav466@gmail.com All Users
Vijay Yadav vjyaav467@gmail.com All Users
Vijay Yadav vjyaav468@gmail.com All Users
Vijay Yadav vjyaav469@gmail.com All Users
Vijay Yadav vjyaav470@gmail.com All Users
Vijay Yadav vjyaav471@gmail.com All Users
Vijay Yadav vjyaav472@gmail.com All Users
Vijay Yadav vjyaav473@gmail.com All Users
Vijay Yadav vjyaav474@gmail.com All Users
Vijay Yadav vjyaav475@gmail.com All Users
Vijay Yadav vjyaav476@gmail.com All Users
Vijay Yadav vjyaav477@gmail.com All Users
Vijay Yadav vjyaav478@gmail.com All Users
Vijay Yadav vjyaav479@gmail.com All Users
Vijay Yadav vjyaav480@gmail.com All Users
Vijay Yadav vjyaav481@gmail.com All Users
Vijay Yadav vjyaav482@gmail.com All Users
Vijay Yadav vjyaav483@gmail.com All Users
Vijay Yadav vjyaav484@gmail.com All Users
Vijay Yadav vjyaav485@gmail.com All Users
Vijay Yadav vjyaav486@gmail.com All Users
Vijay Yadav vjyaav487@gmail.com All Users
Vijay Yadav vjyaav488@gmail.com All Users
Vijay Yadav vjyaav489@gmail.com All Users
Vijay Yadav vjyaav490@gmail.com All Users
Vijay Yadav vjyaav491@gmail.com All Users
Vijay Yadav vjyaav492@gmail.com All Users
Vijay Yadav vjyaav493@gmail.com All Users
Vijay Yadav vjyaav494@gmail.com All Users
Vijay Yadav vjyaav495@gmail.com All Users
Vijay Yadav vjyaav496@gmail.com All Users
Vijay Yadav vjyaav497@gmail.com All Users
Vijay Yadav vjyaav498@gmail.com All Users
Vijay Yadav vjyaav499@gmail.com All Users
Vijay Yadav vjyaav500@gmail.com All Users
Vijay Yadav vjyaav501@gmail.com All Users
Vijay Yadav vjyaav502@gmail.com All Users
Vijay Yadav vjyaav503@gmail.com All Users
Vijay Yadav vjyaav504@gmail.com All Users
Vijay Yadav vjyaav505@gmail.com All Users
Vijay Yadav vjyaav506@gmail.com All Users
Vijay Yadav vjyaav507@gmail.com All Users
Vijay Yadav vjyaav508@gmail.com All Users
Vijay Yadav vjyaav509@gmail.com All Users

View file

@ -1,6 +1,6 @@
First Name,Last Name,Email,Groups
,,test12empty@gmail.com,All Users
Test,Example,test12empty@gmail.com,All Users
Test,Example,test14empty@gmail.com,All Users
Test,Example,test14empty@gmail.com,All Users
Test,Example,test16empty@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
,,test12empty@gmail.com,Admin,Admin
Test,Example,test12empty@gmail.com,Builder,Builder
Test,Example,test14empty@gmail.com,End User,End User
Test,Example,test14empty@gmail.com,End User,End User
Test,Example,test16empty@gmail.com,End User,End User
1 First Name Last Name Email Groups User Role Group
2 test12empty@gmail.com All Users Admin Admin
3 Test Example test12empty@gmail.com All Users Builder Builder
4 Test Example test14empty@gmail.com All Users End User End User
5 Test Example test14empty@gmail.com All Users End User End User
6 Test Example test16empty@gmail.com All Users End User End User

View file

@ -1,12 +1,3 @@
First Name,Last Name,Email,Groups
Test,Example,test12@gmail.com,All-users
Test,Example,test13@gmail.com,All-users
Test,Example,test14@gmail.com,All-users
Test,Example,test15@gmail.com,All-users
Test,Example,test16@gmail.com,All-users
Test,Example,test17@gmail.com,All-users
Test,Example,test18@gmail.com,All-users
Test,Example,test19@gmail.com,All-users
Test,Example,test20@gmail.com,All-users
Test,Example,test21@gmail.com,All-users
Test,Example,test22@gmail.com,All-users
First Name,Last Name,Email,User Role,Group
Test,Example,test12@gmail.com,Admin,ABC
Test,Example,test13@gmail.com,Builder,Test

1 First Name Last Name Email Groups User Role Group
2 Test Example test12@gmail.com All-users Admin ABC
3 Test Example test13@gmail.com All-users Builder Test
Test Example test14@gmail.com All-users
Test Example test15@gmail.com All-users
Test Example test16@gmail.com All-users
Test Example test17@gmail.com All-users
Test Example test18@gmail.com All-users
Test Example test19@gmail.com All-users
Test Example test20@gmail.com All-users
Test Example test21@gmail.com All-users
Test Example test22@gmail.com All-users

View file

@ -1,251 +1,251 @@
First Name,Last Name,Email,Groups
Test,Example,test12@gmail.com,All Users|Admin
Test,Example,test13@gmail.com,All Users
Test,Example,test14@gmail.com,All Users
Test,Example,test15@gmail.com,All Users
Test,Example,test16@gmail.com,All Users
Test,Example,test17@gmail.com,All Users
Test,Example,test18@gmail.com,All Users
Test,Example,test19@gmail.com,All Users
Test,Example,test20@gmail.com,All Users
Test,Example,test21@gmail.com,All Users
Test,Example,test22@gmail.com,All Users
Test,Example,test23@gmail.com,All Users
Test,Example,test24@gmail.com,All Users
Test,Example,test25@gmail.com,All Users
Test,Example,test26@gmail.com,All Users
Test,Example,test27@gmail.com,All Users
Test,Example,test28@gmail.com,All Users
Test,Example,test29@gmail.com,All Users
Test,Example,test30@gmail.com,All Users
Test,Example,test31@gmail.com,All Users
Test,Example,test32@gmail.com,All Users
Test,Example,test33@gmail.com,All Users
Test,Example,test34@gmail.com,All Users
Test,Example,test35@gmail.com,All Users
Test,Example,test36@gmail.com,All Users
Test,Example,test37@gmail.com,All Users
Test,Example,test38@gmail.com,All Users
Test,Example,test39@gmail.com,All Users
Test,Example,test40@gmail.com,All Users
Test,Example,test41@gmail.com,All Users
Test,Example,test42@gmail.com,All Users
Test,Example,test43@gmail.com,All Users
Test,Example,test44@gmail.com,All Users
Test,Example,test45@gmail.com,All Users
Test,Example,test46@gmail.com,All Users
Test,Example,test47@gmail.com,All Users
Test,Example,test48@gmail.com,All Users
Test,Example,test49@gmail.com,All Users
Test,Example,test50@gmail.com,All Users
Test,Example,test51@gmail.com,All Users
Test,Example,test52@gmail.com,All Users
Test,Example,test53@gmail.com,All Users
Test,Example,test54@gmail.com,All Users
Test,Example,test55@gmail.com,All Users
Test,Example,test56@gmail.com,All Users
Test,Example,test57@gmail.com,All Users
Test,Example,test58@gmail.com,All Users
Test,Example,test59@gmail.com,All Users
Test,Example,test60@gmail.com,All Users
Test,Example,test61@gmail.com,All Users
Test,Example,test62@gmail.com,All Users
Test,Example,test63@gmail.com,All Users
Test,Example,test64@gmail.com,All Users
Test,Example,test65@gmail.com,All Users
Test,Example,test66@gmail.com,All Users
Test,Example,test67@gmail.com,All Users
Test,Example,test68@gmail.com,All Users
Test,Example,test69@gmail.com,All Users
Test,Example,test70@gmail.com,All Users
Test,Example,test71@gmail.com,All Users
Test,Example,test72@gmail.com,All Users
Test,Example,test73@gmail.com,All Users
Test,Example,test74@gmail.com,All Users
Test,Example,test75@gmail.com,All Users
Test,Example,test76@gmail.com,All Users
Test,Example,test77@gmail.com,All Users
Test,Example,test78@gmail.com,All Users
Test,Example,test79@gmail.com,All Users
Test,Example,test80@gmail.com,All Users
Test,Example,test81@gmail.com,All Users
Test,Example,test82@gmail.com,All Users
Test,Example,test83@gmail.com,All Users
Test,Example,test84@gmail.com,All Users
Test,Example,test85@gmail.com,All Users
Test,Example,test86@gmail.com,All Users
Test,Example,test87@gmail.com,All Users
Test,Example,test88@gmail.com,All Users
Test,Example,test89@gmail.com,All Users
Test,Example,test90@gmail.com,All Users
Test,Example,test91@gmail.com,All Users
Test,Example,test92@gmail.com,All Users
Test,Example,test93@gmail.com,All Users
Test,Example,test94@gmail.com,All Users
Test,Example,test95@gmail.com,All Users
Test,Example,test96@gmail.com,All Users
Test,Example,test97@gmail.com,All Users
Test,Example,test98@gmail.com,All Users
Test,Example,test99@gmail.com,All Users
Test,Example,test100@gmail.com,All Users
Test,Example,test101@gmail.com,All Users
Test,Example,test102@gmail.com,All Users
Test,Example,test103@gmail.com,All Users
Test,Example,test104@gmail.com,All Users
Test,Example,test105@gmail.com,All Users
Test,Example,test106@gmail.com,All Users
Test,Example,test107@gmail.com,All Users
Test,Example,test108@gmail.com,All Users
Test,Example,test109@gmail.com,All Users
Test,Example,test110@gmail.com,All Users
Test,Example,test111@gmail.com,All Users
Test,Example,test112@gmail.com,All Users
Test,Example,test113@gmail.com,All Users
Test,Example,test114@gmail.com,All Users
Test,Example,test115@gmail.com,All Users
Test,Example,test116@gmail.com,All Users
Test,Example,test117@gmail.com,All Users
Test,Example,test118@gmail.com,All Users
Test,Example,test119@gmail.com,All Users
Test,Example,test120@gmail.com,All Users
Test,Example,test121@gmail.com,All Users
Test,Example,test122@gmail.com,All Users
Test,Example,test123@gmail.com,All Users
Test,Example,test124@gmail.com,All Users
Test,Example,test125@gmail.com,All Users
Test,Example,test126@gmail.com,All Users
Test,Example,test127@gmail.com,All Users
Test,Example,test128@gmail.com,All Users
Test,Example,test129@gmail.com,All Users
Test,Example,test130@gmail.com,All Users
Test,Example,test131@gmail.com,All Users
Test,Example,test132@gmail.com,All Users
Test,Example,test133@gmail.com,All Users
Test,Example,test134@gmail.com,All Users
Test,Example,test135@gmail.com,All Users
Test,Example,test136@gmail.com,All Users
Test,Example,test137@gmail.com,All Users
Test,Example,test138@gmail.com,All Users
Test,Example,test139@gmail.com,All Users
Test,Example,test140@gmail.com,All Users
Test,Example,test141@gmail.com,All Users
Test,Example,test142@gmail.com,All Users
Test,Example,test143@gmail.com,All Users
Test,Example,test144@gmail.com,All Users
Test,Example,test145@gmail.com,All Users
Test,Example,test146@gmail.com,All Users
Test,Example,test147@gmail.com,All Users
Test,Example,test148@gmail.com,All Users
Test,Example,test149@gmail.com,All Users
Test,Example,test150@gmail.com,All Users
Test,Example,test151@gmail.com,All Users
Test,Example,test152@gmail.com,All Users
Test,Example,test153@gmail.com,All Users
Test,Example,test154@gmail.com,All Users
Test,Example,test155@gmail.com,All Users
Test,Example,test156@gmail.com,All Users
Test,Example,test157@gmail.com,All Users
Test,Example,test158@gmail.com,All Users
Test,Example,test159@gmail.com,All Users
Test,Example,test160@gmail.com,All Users
Test,Example,test161@gmail.com,All Users
Test,Example,test162@gmail.com,All Users
Test,Example,test163@gmail.com,All Users
Test,Example,test164@gmail.com,All Users
Test,Example,test165@gmail.com,All Users
Test,Example,test166@gmail.com,All Users
Test,Example,test167@gmail.com,All Users
Test,Example,test168@gmail.com,All Users
Test,Example,test169@gmail.com,All Users
Test,Example,test170@gmail.com,All Users
Test,Example,test171@gmail.com,All Users
Test,Example,test172@gmail.com,All Users
Test,Example,test173@gmail.com,All Users
Test,Example,test174@gmail.com,All Users
Test,Example,test175@gmail.com,All Users
Test,Example,test176@gmail.com,All Users
Test,Example,test177@gmail.com,All Users
Test,Example,test178@gmail.com,All Users
Test,Example,test179@gmail.com,All Users
Test,Example,test180@gmail.com,All Users
Test,Example,test181@gmail.com,All Users
Test,Example,test182@gmail.com,All Users
Test,Example,test183@gmail.com,All Users
Test,Example,test184@gmail.com,All Users
Test,Example,test185@gmail.com,All Users
Test,Example,test186@gmail.com,All Users
Test,Example,test187@gmail.com,All Users
Test,Example,test188@gmail.com,All Users
Test,Example,test189@gmail.com,All Users
Test,Example,test190@gmail.com,All Users
Test,Example,test191@gmail.com,All Users
Test,Example,test192@gmail.com,All Users
Test,Example,test193@gmail.com,All Users
Test,Example,test194@gmail.com,All Users
Test,Example,test195@gmail.com,All Users
Test,Example,test196@gmail.com,All Users
Test,Example,test197@gmail.com,All Users
Test,Example,test198@gmail.com,All Users
Test,Example,test199@gmail.com,All Users
Test,Example,test200@gmail.com,All Users
Test,Example,test201@gmail.com,All Users
Test,Example,test202@gmail.com,All Users
Test,Example,test203@gmail.com,All Users
Test,Example,test204@gmail.com,All Users
Test,Example,test205@gmail.com,All Users
Test,Example,test206@gmail.com,All Users
Test,Example,test207@gmail.com,All Users
Test,Example,test208@gmail.com,All Users
Test,Example,test209@gmail.com,All Users
Test,Example,test210@gmail.com,All Users
Test,Example,test211@gmail.com,All Users
Test,Example,test212@gmail.com,All Users
Test,Example,test213@gmail.com,All Users
Test,Example,test214@gmail.com,All Users
Test,Example,test215@gmail.com,All Users
Test,Example,test216@gmail.com,All Users
Test,Example,test217@gmail.com,All Users
Test,Example,test218@gmail.com,All Users
Test,Example,test219@gmail.com,All Users
Test,Example,test220@gmail.com,All Users
Test,Example,test221@gmail.com,All Users
Test,Example,test222@gmail.com,All Users
Test,Example,test223@gmail.com,All Users
Test,Example,test224@gmail.com,All Users
Test,Example,test225@gmail.com,All Users
Test,Example,test226@gmail.com,All Users
Test,Example,test227@gmail.com,All Users
Test,Example,test228@gmail.com,All Users
Test,Example,test229@gmail.com,All Users
Test,Example,test230@gmail.com,All Users
Test,Example,test231@gmail.com,All Users
Test,Example,test232@gmail.com,All Users
Test,Example,test233@gmail.com,All Users
Test,Example,test234@gmail.com,All Users
Test,Example,test235@gmail.com,All Users
Test,Example,test236@gmail.com,All Users
Test,Example,test237@gmail.com,All Users
Test,Example,test238@gmail.com,All Users
Test,Example,test239@gmail.com,All Users
Test,Example,test240@gmail.com,All Users
Test,Example,test241@gmail.com,All Users
Test,Example,test242@gmail.com,All Users
Test,Example,test243@gmail.com,All Users
Test,Example,test244@gmail.com,All Users
Test,Example,test245@gmail.com,All Users
Test,Example,test246@gmail.com,All Users
Test,Example,test247@gmail.com,All Users
Test,Example,test248@gmail.com,All Users
Test,Example,test249@gmail.com,All Users
Test,Example,test250@gmail.com,All Users
Test,Example,test251@gmail.com,All Users
Test,Example,test252@gmail.com,All Users
Test,Example,test253@gmail.com,All Users
Test,Example,test254@gmail.com,All Users
Test,Example,test255@gmail.com,All Users
Test,Example,test256@gmail.com,All Users
Test,Example,test257@gmail.com,All Users
Test,Example,test258@gmail.com,All Users
Test,Example,test259@gmail.com,All Users
Test,Example,test260@gmail.com,All Users
Test,Example,test261@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
test,test,test1@gmail.com,Admin,Admin
test,test,test2@gmail.com,Builder,Builder
test,test,test3@gmail.com,Builder,Builder
test,test,test4@gmail.com,End User,End User
test,test,test5@gmail.com,End User,End User
test,test,test6@gmail.com,End User,End User
test,test,test7@gmail.com,End User,End User
test,test,test8@gmail.com,End User,End User
test,test,test9@gmail.com,End User,End User
test,test,test10@gmail.com,End User,End User
test,test,test11@gmail.com,End User,End User
test,test,test12@gmail.com,End User,End User
test,test,test13@gmail.com,End User,End User
test,test,test14@gmail.com,End User,End User
test,test,test15@gmail.com,End User,End User
test,test,test16@gmail.com,End User,End User
test,test,test17@gmail.com,End User,End User
test,test,test18@gmail.com,End User,End User
test,test,test19@gmail.com,End User,End User
test,test,test20@gmail.com,End User,End User
test,test,test21@gmail.com,End User,End User
test,test,test22@gmail.com,End User,End User
test,test,test23@gmail.com,End User,End User
test,test,test24@gmail.com,End User,End User
test,test,test25@gmail.com,End User,End User
test,test,test26@gmail.com,End User,End User
test,test,test27@gmail.com,End User,End User
test,test,test28@gmail.com,End User,End User
test,test,test29@gmail.com,End User,End User
test,test,test30@gmail.com,End User,End User
test,test,test31@gmail.com,End User,End User
test,test,test32@gmail.com,End User,End User
test,test,test33@gmail.com,End User,End User
test,test,test34@gmail.com,End User,End User
test,test,test35@gmail.com,End User,End User
test,test,test36@gmail.com,End User,End User
test,test,test37@gmail.com,End User,End User
test,test,test38@gmail.com,End User,End User
test,test,test39@gmail.com,End User,End User
test,test,test40@gmail.com,End User,End User
test,test,test41@gmail.com,End User,End User
test,test,test42@gmail.com,End User,End User
test,test,test43@gmail.com,End User,End User
test,test,test44@gmail.com,End User,End User
test,test,test45@gmail.com,End User,End User
test,test,test46@gmail.com,End User,End User
test,test,test47@gmail.com,End User,End User
test,test,test48@gmail.com,End User,End User
test,test,test49@gmail.com,End User,End User
test,test,test50@gmail.com,End User,End User
test,test,test51@gmail.com,End User,End User
test,test,test52@gmail.com,End User,End User
test,test,test53@gmail.com,End User,End User
test,test,test54@gmail.com,End User,End User
test,test,test55@gmail.com,End User,End User
test,test,test56@gmail.com,End User,End User
test,test,test57@gmail.com,End User,End User
test,test,test58@gmail.com,End User,End User
test,test,test59@gmail.com,End User,End User
test,test,test60@gmail.com,End User,End User
test,test,test61@gmail.com,End User,End User
test,test,test62@gmail.com,End User,End User
test,test,test63@gmail.com,End User,End User
test,test,test64@gmail.com,End User,End User
test,test,test65@gmail.com,End User,End User
test,test,test66@gmail.com,End User,End User
test,test,test67@gmail.com,End User,End User
test,test,test68@gmail.com,End User,End User
test,test,test69@gmail.com,End User,End User
test,test,test70@gmail.com,End User,End User
test,test,test71@gmail.com,End User,End User
test,test,test72@gmail.com,End User,End User
test,test,test73@gmail.com,End User,End User
test,test,test74@gmail.com,End User,End User
test,test,test75@gmail.com,End User,End User
test,test,test76@gmail.com,End User,End User
test,test,test77@gmail.com,End User,End User
test,test,test78@gmail.com,End User,End User
test,test,test79@gmail.com,End User,End User
test,test,test80@gmail.com,End User,End User
test,test,test81@gmail.com,End User,End User
test,test,test82@gmail.com,End User,End User
test,test,test83@gmail.com,End User,End User
test,test,test84@gmail.com,End User,End User
test,test,test85@gmail.com,End User,End User
test,test,test86@gmail.com,End User,End User
test,test,test87@gmail.com,End User,End User
test,test,test88@gmail.com,End User,End User
test,test,test89@gmail.com,End User,End User
test,test,test90@gmail.com,End User,End User
test,test,test91@gmail.com,End User,End User
test,test,test92@gmail.com,End User,End User
test,test,test93@gmail.com,End User,End User
test,test,test94@gmail.com,End User,End User
test,test,test95@gmail.com,End User,End User
test,test,test96@gmail.com,End User,End User
test,test,test97@gmail.com,End User,End User
test,test,test98@gmail.com,End User,End User
test,test,test99@gmail.com,End User,End User
test,test,test100@gmail.com,End User,End User
test,test,test101@gmail.com,End User,End User
test,test,test102@gmail.com,End User,End User
test,test,test103@gmail.com,End User,End User
test,test,test104@gmail.com,End User,End User
test,test,test105@gmail.com,End User,End User
test,test,test106@gmail.com,End User,End User
test,test,test107@gmail.com,End User,End User
test,test,test108@gmail.com,End User,End User
test,test,test109@gmail.com,End User,End User
test,test,test110@gmail.com,End User,End User
test,test,test111@gmail.com,End User,End User
test,test,test112@gmail.com,End User,End User
test,test,test113@gmail.com,End User,End User
test,test,test114@gmail.com,End User,End User
test,test,test115@gmail.com,End User,End User
test,test,test116@gmail.com,End User,End User
test,test,test117@gmail.com,End User,End User
test,test,test118@gmail.com,End User,End User
test,test,test119@gmail.com,End User,End User
test,test,test120@gmail.com,End User,End User
test,test,test121@gmail.com,End User,End User
test,test,test122@gmail.com,End User,End User
test,test,test123@gmail.com,End User,End User
test,test,test124@gmail.com,End User,End User
test,test,test125@gmail.com,End User,End User
test,test,test126@gmail.com,End User,End User
test,test,test127@gmail.com,End User,End User
test,test,test128@gmail.com,End User,End User
test,test,test129@gmail.com,End User,End User
test,test,test130@gmail.com,End User,End User
test,test,test131@gmail.com,End User,End User
test,test,test132@gmail.com,End User,End User
test,test,test133@gmail.com,End User,End User
test,test,test134@gmail.com,End User,End User
test,test,test135@gmail.com,End User,End User
test,test,test136@gmail.com,End User,End User
test,test,test137@gmail.com,End User,End User
test,test,test138@gmail.com,End User,End User
test,test,test139@gmail.com,End User,End User
test,test,test140@gmail.com,End User,End User
test,test,test141@gmail.com,End User,End User
test,test,test142@gmail.com,End User,End User
test,test,test143@gmail.com,End User,End User
test,test,test144@gmail.com,End User,End User
test,test,test145@gmail.com,End User,End User
test,test,test146@gmail.com,End User,End User
test,test,test147@gmail.com,End User,End User
test,test,test148@gmail.com,End User,End User
test,test,test149@gmail.com,End User,End User
test,test,test150@gmail.com,End User,End User
test,test,test151@gmail.com,End User,End User
test,test,test152@gmail.com,End User,End User
test,test,test153@gmail.com,End User,End User
test,test,test154@gmail.com,End User,End User
test,test,test155@gmail.com,End User,End User
test,test,test156@gmail.com,End User,End User
test,test,test157@gmail.com,End User,End User
test,test,test158@gmail.com,End User,End User
test,test,test159@gmail.com,End User,End User
test,test,test160@gmail.com,End User,End User
test,test,test161@gmail.com,End User,End User
test,test,test162@gmail.com,End User,End User
test,test,test163@gmail.com,End User,End User
test,test,test164@gmail.com,End User,End User
test,test,test165@gmail.com,End User,End User
test,test,test166@gmail.com,End User,End User
test,test,test167@gmail.com,End User,End User
test,test,test168@gmail.com,End User,End User
test,test,test169@gmail.com,End User,End User
test,test,test170@gmail.com,End User,End User
test,test,test171@gmail.com,End User,End User
test,test,test172@gmail.com,End User,End User
test,test,test173@gmail.com,End User,End User
test,test,test174@gmail.com,End User,End User
test,test,test175@gmail.com,End User,End User
test,test,test176@gmail.com,End User,End User
test,test,test177@gmail.com,End User,End User
test,test,test178@gmail.com,End User,End User
test,test,test179@gmail.com,End User,End User
test,test,test180@gmail.com,End User,End User
test,test,test181@gmail.com,End User,End User
test,test,test182@gmail.com,End User,End User
test,test,test183@gmail.com,End User,End User
test,test,test184@gmail.com,End User,End User
test,test,test185@gmail.com,End User,End User
test,test,test186@gmail.com,End User,End User
test,test,test187@gmail.com,End User,End User
test,test,test188@gmail.com,End User,End User
test,test,test189@gmail.com,End User,End User
test,test,test190@gmail.com,End User,End User
test,test,test191@gmail.com,End User,End User
test,test,test192@gmail.com,End User,End User
test,test,test193@gmail.com,End User,End User
test,test,test194@gmail.com,End User,End User
test,test,test195@gmail.com,End User,End User
test,test,test196@gmail.com,End User,End User
test,test,test197@gmail.com,End User,End User
test,test,test198@gmail.com,End User,End User
test,test,test199@gmail.com,End User,End User
test,test,test200@gmail.com,End User,End User
test,test,test201@gmail.com,End User,End User
test,test,test202@gmail.com,End User,End User
test,test,test203@gmail.com,End User,End User
test,test,test204@gmail.com,End User,End User
test,test,test205@gmail.com,End User,End User
test,test,test206@gmail.com,End User,End User
test,test,test207@gmail.com,End User,End User
test,test,test208@gmail.com,End User,End User
test,test,test209@gmail.com,End User,End User
test,test,test210@gmail.com,End User,End User
test,test,test211@gmail.com,End User,End User
test,test,test212@gmail.com,End User,End User
test,test,test213@gmail.com,End User,End User
test,test,test214@gmail.com,End User,End User
test,test,test215@gmail.com,End User,End User
test,test,test216@gmail.com,End User,End User
test,test,test217@gmail.com,End User,End User
test,test,test218@gmail.com,End User,End User
test,test,test219@gmail.com,End User,End User
test,test,test220@gmail.com,End User,End User
test,test,test221@gmail.com,End User,End User
test,test,test222@gmail.com,End User,End User
test,test,test223@gmail.com,End User,End User
test,test,test224@gmail.com,End User,End User
test,test,test225@gmail.com,End User,End User
test,test,test226@gmail.com,End User,End User
test,test,test227@gmail.com,End User,End User
test,test,test228@gmail.com,End User,End User
test,test,test229@gmail.com,End User,End User
test,test,test230@gmail.com,End User,End User
test,test,test231@gmail.com,End User,End User
test,test,test232@gmail.com,End User,End User
test,test,test233@gmail.com,End User,End User
test,test,test234@gmail.com,End User,End User
test,test,test235@gmail.com,End User,End User
test,test,test236@gmail.com,End User,End User
test,test,test237@gmail.com,End User,End User
test,test,test238@gmail.com,End User,End User
test,test,test239@gmail.com,End User,End User
test,test,test240@gmail.com,End User,End User
test,test,test241@gmail.com,End User,End User
test,test,test242@gmail.com,End User,End User
test,test,test243@gmail.com,End User,End User
test,test,test244@gmail.com,End User,End User
test,test,test245@gmail.com,End User,End User
test,test,test246@gmail.com,End User,End User
test,test,test247@gmail.com,End User,End User
test,test,test248@gmail.com,End User,End User
test,test,test249@gmail.com,End User,End User
test,test,test250@gmail.com,End User,End User
1 First Name Last Name Email Groups User Role Group
2 Test test Example test test12@gmail.com test1@gmail.com All Users|Admin Admin Admin
3 Test test Example test test13@gmail.com test2@gmail.com All Users Builder Builder
4 Test test Example test test14@gmail.com test3@gmail.com All Users Builder Builder
5 Test test Example test test15@gmail.com test4@gmail.com All Users End User End User
6 Test test Example test test16@gmail.com test5@gmail.com All Users End User End User
7 Test test Example test test17@gmail.com test6@gmail.com All Users End User End User
8 Test test Example test test18@gmail.com test7@gmail.com All Users End User End User
9 Test test Example test test19@gmail.com test8@gmail.com All Users End User End User
10 Test test Example test test20@gmail.com test9@gmail.com All Users End User End User
11 Test test Example test test21@gmail.com test10@gmail.com All Users End User End User
12 Test test Example test test22@gmail.com test11@gmail.com All Users End User End User
13 Test test Example test test23@gmail.com test12@gmail.com All Users End User End User
14 Test test Example test test24@gmail.com test13@gmail.com All Users End User End User
15 Test test Example test test25@gmail.com test14@gmail.com All Users End User End User
16 Test test Example test test26@gmail.com test15@gmail.com All Users End User End User
17 Test test Example test test27@gmail.com test16@gmail.com All Users End User End User
18 Test test Example test test28@gmail.com test17@gmail.com All Users End User End User
19 Test test Example test test29@gmail.com test18@gmail.com All Users End User End User
20 Test test Example test test30@gmail.com test19@gmail.com All Users End User End User
21 Test test Example test test31@gmail.com test20@gmail.com All Users End User End User
22 Test test Example test test32@gmail.com test21@gmail.com All Users End User End User
23 Test test Example test test33@gmail.com test22@gmail.com All Users End User End User
24 Test test Example test test34@gmail.com test23@gmail.com All Users End User End User
25 Test test Example test test35@gmail.com test24@gmail.com All Users End User End User
26 Test test Example test test36@gmail.com test25@gmail.com All Users End User End User
27 Test test Example test test37@gmail.com test26@gmail.com All Users End User End User
28 Test test Example test test38@gmail.com test27@gmail.com All Users End User End User
29 Test test Example test test39@gmail.com test28@gmail.com All Users End User End User
30 Test test Example test test40@gmail.com test29@gmail.com All Users End User End User
31 Test test Example test test41@gmail.com test30@gmail.com All Users End User End User
32 Test test Example test test42@gmail.com test31@gmail.com All Users End User End User
33 Test test Example test test43@gmail.com test32@gmail.com All Users End User End User
34 Test test Example test test44@gmail.com test33@gmail.com All Users End User End User
35 Test test Example test test45@gmail.com test34@gmail.com All Users End User End User
36 Test test Example test test46@gmail.com test35@gmail.com All Users End User End User
37 Test test Example test test47@gmail.com test36@gmail.com All Users End User End User
38 Test test Example test test48@gmail.com test37@gmail.com All Users End User End User
39 Test test Example test test49@gmail.com test38@gmail.com All Users End User End User
40 Test test Example test test50@gmail.com test39@gmail.com All Users End User End User
41 Test test Example test test51@gmail.com test40@gmail.com All Users End User End User
42 Test test Example test test52@gmail.com test41@gmail.com All Users End User End User
43 Test test Example test test53@gmail.com test42@gmail.com All Users End User End User
44 Test test Example test test54@gmail.com test43@gmail.com All Users End User End User
45 Test test Example test test55@gmail.com test44@gmail.com All Users End User End User
46 Test test Example test test56@gmail.com test45@gmail.com All Users End User End User
47 Test test Example test test57@gmail.com test46@gmail.com All Users End User End User
48 Test test Example test test58@gmail.com test47@gmail.com All Users End User End User
49 Test test Example test test59@gmail.com test48@gmail.com All Users End User End User
50 Test test Example test test60@gmail.com test49@gmail.com All Users End User End User
51 Test test Example test test61@gmail.com test50@gmail.com All Users End User End User
52 Test test Example test test62@gmail.com test51@gmail.com All Users End User End User
53 Test test Example test test63@gmail.com test52@gmail.com All Users End User End User
54 Test test Example test test64@gmail.com test53@gmail.com All Users End User End User
55 Test test Example test test65@gmail.com test54@gmail.com All Users End User End User
56 Test test Example test test66@gmail.com test55@gmail.com All Users End User End User
57 Test test Example test test67@gmail.com test56@gmail.com All Users End User End User
58 Test test Example test test68@gmail.com test57@gmail.com All Users End User End User
59 Test test Example test test69@gmail.com test58@gmail.com All Users End User End User
60 Test test Example test test70@gmail.com test59@gmail.com All Users End User End User
61 Test test Example test test71@gmail.com test60@gmail.com All Users End User End User
62 Test test Example test test72@gmail.com test61@gmail.com All Users End User End User
63 Test test Example test test73@gmail.com test62@gmail.com All Users End User End User
64 Test test Example test test74@gmail.com test63@gmail.com All Users End User End User
65 Test test Example test test75@gmail.com test64@gmail.com All Users End User End User
66 Test test Example test test76@gmail.com test65@gmail.com All Users End User End User
67 Test test Example test test77@gmail.com test66@gmail.com All Users End User End User
68 Test test Example test test78@gmail.com test67@gmail.com All Users End User End User
69 Test test Example test test79@gmail.com test68@gmail.com All Users End User End User
70 Test test Example test test80@gmail.com test69@gmail.com All Users End User End User
71 Test test Example test test81@gmail.com test70@gmail.com All Users End User End User
72 Test test Example test test82@gmail.com test71@gmail.com All Users End User End User
73 Test test Example test test83@gmail.com test72@gmail.com All Users End User End User
74 Test test Example test test84@gmail.com test73@gmail.com All Users End User End User
75 Test test Example test test85@gmail.com test74@gmail.com All Users End User End User
76 Test test Example test test86@gmail.com test75@gmail.com All Users End User End User
77 Test test Example test test87@gmail.com test76@gmail.com All Users End User End User
78 Test test Example test test88@gmail.com test77@gmail.com All Users End User End User
79 Test test Example test test89@gmail.com test78@gmail.com All Users End User End User
80 Test test Example test test90@gmail.com test79@gmail.com All Users End User End User
81 Test test Example test test91@gmail.com test80@gmail.com All Users End User End User
82 Test test Example test test92@gmail.com test81@gmail.com All Users End User End User
83 Test test Example test test93@gmail.com test82@gmail.com All Users End User End User
84 Test test Example test test94@gmail.com test83@gmail.com All Users End User End User
85 Test test Example test test95@gmail.com test84@gmail.com All Users End User End User
86 Test test Example test test96@gmail.com test85@gmail.com All Users End User End User
87 Test test Example test test97@gmail.com test86@gmail.com All Users End User End User
88 Test test Example test test98@gmail.com test87@gmail.com All Users End User End User
89 Test test Example test test99@gmail.com test88@gmail.com All Users End User End User
90 Test test Example test test100@gmail.com test89@gmail.com All Users End User End User
91 Test test Example test test101@gmail.com test90@gmail.com All Users End User End User
92 Test test Example test test102@gmail.com test91@gmail.com All Users End User End User
93 Test test Example test test103@gmail.com test92@gmail.com All Users End User End User
94 Test test Example test test104@gmail.com test93@gmail.com All Users End User End User
95 Test test Example test test105@gmail.com test94@gmail.com All Users End User End User
96 Test test Example test test106@gmail.com test95@gmail.com All Users End User End User
97 Test test Example test test107@gmail.com test96@gmail.com All Users End User End User
98 Test test Example test test108@gmail.com test97@gmail.com All Users End User End User
99 Test test Example test test109@gmail.com test98@gmail.com All Users End User End User
100 Test test Example test test110@gmail.com test99@gmail.com All Users End User End User
101 Test test Example test test111@gmail.com test100@gmail.com All Users End User End User
102 Test test Example test test112@gmail.com test101@gmail.com All Users End User End User
103 Test test Example test test113@gmail.com test102@gmail.com All Users End User End User
104 Test test Example test test114@gmail.com test103@gmail.com All Users End User End User
105 Test test Example test test115@gmail.com test104@gmail.com All Users End User End User
106 Test test Example test test116@gmail.com test105@gmail.com All Users End User End User
107 Test test Example test test117@gmail.com test106@gmail.com All Users End User End User
108 Test test Example test test118@gmail.com test107@gmail.com All Users End User End User
109 Test test Example test test119@gmail.com test108@gmail.com All Users End User End User
110 Test test Example test test120@gmail.com test109@gmail.com All Users End User End User
111 Test test Example test test121@gmail.com test110@gmail.com All Users End User End User
112 Test test Example test test122@gmail.com test111@gmail.com All Users End User End User
113 Test test Example test test123@gmail.com test112@gmail.com All Users End User End User
114 Test test Example test test124@gmail.com test113@gmail.com All Users End User End User
115 Test test Example test test125@gmail.com test114@gmail.com All Users End User End User
116 Test test Example test test126@gmail.com test115@gmail.com All Users End User End User
117 Test test Example test test127@gmail.com test116@gmail.com All Users End User End User
118 Test test Example test test128@gmail.com test117@gmail.com All Users End User End User
119 Test test Example test test129@gmail.com test118@gmail.com All Users End User End User
120 Test test Example test test130@gmail.com test119@gmail.com All Users End User End User
121 Test test Example test test131@gmail.com test120@gmail.com All Users End User End User
122 Test test Example test test132@gmail.com test121@gmail.com All Users End User End User
123 Test test Example test test133@gmail.com test122@gmail.com All Users End User End User
124 Test test Example test test134@gmail.com test123@gmail.com All Users End User End User
125 Test test Example test test135@gmail.com test124@gmail.com All Users End User End User
126 Test test Example test test136@gmail.com test125@gmail.com All Users End User End User
127 Test test Example test test137@gmail.com test126@gmail.com All Users End User End User
128 Test test Example test test138@gmail.com test127@gmail.com All Users End User End User
129 Test test Example test test139@gmail.com test128@gmail.com All Users End User End User
130 Test test Example test test140@gmail.com test129@gmail.com All Users End User End User
131 Test test Example test test141@gmail.com test130@gmail.com All Users End User End User
132 Test test Example test test142@gmail.com test131@gmail.com All Users End User End User
133 Test test Example test test143@gmail.com test132@gmail.com All Users End User End User
134 Test test Example test test144@gmail.com test133@gmail.com All Users End User End User
135 Test test Example test test145@gmail.com test134@gmail.com All Users End User End User
136 Test test Example test test146@gmail.com test135@gmail.com All Users End User End User
137 Test test Example test test147@gmail.com test136@gmail.com All Users End User End User
138 Test test Example test test148@gmail.com test137@gmail.com All Users End User End User
139 Test test Example test test149@gmail.com test138@gmail.com All Users End User End User
140 Test test Example test test150@gmail.com test139@gmail.com All Users End User End User
141 Test test Example test test151@gmail.com test140@gmail.com All Users End User End User
142 Test test Example test test152@gmail.com test141@gmail.com All Users End User End User
143 Test test Example test test153@gmail.com test142@gmail.com All Users End User End User
144 Test test Example test test154@gmail.com test143@gmail.com All Users End User End User
145 Test test Example test test155@gmail.com test144@gmail.com All Users End User End User
146 Test test Example test test156@gmail.com test145@gmail.com All Users End User End User
147 Test test Example test test157@gmail.com test146@gmail.com All Users End User End User
148 Test test Example test test158@gmail.com test147@gmail.com All Users End User End User
149 Test test Example test test159@gmail.com test148@gmail.com All Users End User End User
150 Test test Example test test160@gmail.com test149@gmail.com All Users End User End User
151 Test test Example test test161@gmail.com test150@gmail.com All Users End User End User
152 Test test Example test test162@gmail.com test151@gmail.com All Users End User End User
153 Test test Example test test163@gmail.com test152@gmail.com All Users End User End User
154 Test test Example test test164@gmail.com test153@gmail.com All Users End User End User
155 Test test Example test test165@gmail.com test154@gmail.com All Users End User End User
156 Test test Example test test166@gmail.com test155@gmail.com All Users End User End User
157 Test test Example test test167@gmail.com test156@gmail.com All Users End User End User
158 Test test Example test test168@gmail.com test157@gmail.com All Users End User End User
159 Test test Example test test169@gmail.com test158@gmail.com All Users End User End User
160 Test test Example test test170@gmail.com test159@gmail.com All Users End User End User
161 Test test Example test test171@gmail.com test160@gmail.com All Users End User End User
162 Test test Example test test172@gmail.com test161@gmail.com All Users End User End User
163 Test test Example test test173@gmail.com test162@gmail.com All Users End User End User
164 Test test Example test test174@gmail.com test163@gmail.com All Users End User End User
165 Test test Example test test175@gmail.com test164@gmail.com All Users End User End User
166 Test test Example test test176@gmail.com test165@gmail.com All Users End User End User
167 Test test Example test test177@gmail.com test166@gmail.com All Users End User End User
168 Test test Example test test178@gmail.com test167@gmail.com All Users End User End User
169 Test test Example test test179@gmail.com test168@gmail.com All Users End User End User
170 Test test Example test test180@gmail.com test169@gmail.com All Users End User End User
171 Test test Example test test181@gmail.com test170@gmail.com All Users End User End User
172 Test test Example test test182@gmail.com test171@gmail.com All Users End User End User
173 Test test Example test test183@gmail.com test172@gmail.com All Users End User End User
174 Test test Example test test184@gmail.com test173@gmail.com All Users End User End User
175 Test test Example test test185@gmail.com test174@gmail.com All Users End User End User
176 Test test Example test test186@gmail.com test175@gmail.com All Users End User End User
177 Test test Example test test187@gmail.com test176@gmail.com All Users End User End User
178 Test test Example test test188@gmail.com test177@gmail.com All Users End User End User
179 Test test Example test test189@gmail.com test178@gmail.com All Users End User End User
180 Test test Example test test190@gmail.com test179@gmail.com All Users End User End User
181 Test test Example test test191@gmail.com test180@gmail.com All Users End User End User
182 Test test Example test test192@gmail.com test181@gmail.com All Users End User End User
183 Test test Example test test193@gmail.com test182@gmail.com All Users End User End User
184 Test test Example test test194@gmail.com test183@gmail.com All Users End User End User
185 Test test Example test test195@gmail.com test184@gmail.com All Users End User End User
186 Test test Example test test196@gmail.com test185@gmail.com All Users End User End User
187 Test test Example test test197@gmail.com test186@gmail.com All Users End User End User
188 Test test Example test test198@gmail.com test187@gmail.com All Users End User End User
189 Test test Example test test199@gmail.com test188@gmail.com All Users End User End User
190 Test test Example test test200@gmail.com test189@gmail.com All Users End User End User
191 Test test Example test test201@gmail.com test190@gmail.com All Users End User End User
192 Test test Example test test202@gmail.com test191@gmail.com All Users End User End User
193 Test test Example test test203@gmail.com test192@gmail.com All Users End User End User
194 Test test Example test test204@gmail.com test193@gmail.com All Users End User End User
195 Test test Example test test205@gmail.com test194@gmail.com All Users End User End User
196 Test test Example test test206@gmail.com test195@gmail.com All Users End User End User
197 Test test Example test test207@gmail.com test196@gmail.com All Users End User End User
198 Test test Example test test208@gmail.com test197@gmail.com All Users End User End User
199 Test test Example test test209@gmail.com test198@gmail.com All Users End User End User
200 Test test Example test test210@gmail.com test199@gmail.com All Users End User End User
201 Test test Example test test211@gmail.com test200@gmail.com All Users End User End User
202 Test test Example test test212@gmail.com test201@gmail.com All Users End User End User
203 Test test Example test test213@gmail.com test202@gmail.com All Users End User End User
204 Test test Example test test214@gmail.com test203@gmail.com All Users End User End User
205 Test test Example test test215@gmail.com test204@gmail.com All Users End User End User
206 Test test Example test test216@gmail.com test205@gmail.com All Users End User End User
207 Test test Example test test217@gmail.com test206@gmail.com All Users End User End User
208 Test test Example test test218@gmail.com test207@gmail.com All Users End User End User
209 Test test Example test test219@gmail.com test208@gmail.com All Users End User End User
210 Test test Example test test220@gmail.com test209@gmail.com All Users End User End User
211 Test test Example test test221@gmail.com test210@gmail.com All Users End User End User
212 Test test Example test test222@gmail.com test211@gmail.com All Users End User End User
213 Test test Example test test223@gmail.com test212@gmail.com All Users End User End User
214 Test test Example test test224@gmail.com test213@gmail.com All Users End User End User
215 Test test Example test test225@gmail.com test214@gmail.com All Users End User End User
216 Test test Example test test226@gmail.com test215@gmail.com All Users End User End User
217 Test test Example test test227@gmail.com test216@gmail.com All Users End User End User
218 Test test Example test test228@gmail.com test217@gmail.com All Users End User End User
219 Test test Example test test229@gmail.com test218@gmail.com All Users End User End User
220 Test test Example test test230@gmail.com test219@gmail.com All Users End User End User
221 Test test Example test test231@gmail.com test220@gmail.com All Users End User End User
222 Test test Example test test232@gmail.com test221@gmail.com All Users End User End User
223 Test test Example test test233@gmail.com test222@gmail.com All Users End User End User
224 Test test Example test test234@gmail.com test223@gmail.com All Users End User End User
225 Test test Example test test235@gmail.com test224@gmail.com All Users End User End User
226 Test test Example test test236@gmail.com test225@gmail.com All Users End User End User
227 Test test Example test test237@gmail.com test226@gmail.com All Users End User End User
228 Test test Example test test238@gmail.com test227@gmail.com All Users End User End User
229 Test test Example test test239@gmail.com test228@gmail.com All Users End User End User
230 Test test Example test test240@gmail.com test229@gmail.com All Users End User End User
231 Test test Example test test241@gmail.com test230@gmail.com All Users End User End User
232 Test test Example test test242@gmail.com test231@gmail.com All Users End User End User
233 Test test Example test test243@gmail.com test232@gmail.com All Users End User End User
234 Test test Example test test244@gmail.com test233@gmail.com All Users End User End User
235 Test test Example test test245@gmail.com test234@gmail.com All Users End User End User
236 Test test Example test test246@gmail.com test235@gmail.com All Users End User End User
237 Test test Example test test247@gmail.com test236@gmail.com All Users End User End User
238 Test test Example test test248@gmail.com test237@gmail.com All Users End User End User
239 Test test Example test test249@gmail.com test238@gmail.com All Users End User End User
240 Test test Example test test250@gmail.com test239@gmail.com All Users End User End User
241 Test test Example test test251@gmail.com test240@gmail.com All Users End User End User
242 Test test Example test test252@gmail.com test241@gmail.com All Users End User End User
243 Test test Example test test253@gmail.com test242@gmail.com All Users End User End User
244 Test test Example test test254@gmail.com test243@gmail.com All Users End User End User
245 Test test Example test test255@gmail.com test244@gmail.com All Users End User End User
246 Test test Example test test256@gmail.com test245@gmail.com All Users End User End User
247 Test test Example test test257@gmail.com test246@gmail.com All Users End User End User
248 Test test Example test test258@gmail.com test247@gmail.com All Users End User End User
249 Test test Example test test259@gmail.com test248@gmail.com All Users End User End User
250 Test test Example test test260@gmail.com test249@gmail.com All Users End User End User
251 Test test Example test test261@gmail.com test250@gmail.com All Users End User End User

View file

@ -1,7 +1,7 @@
First Name,Last Name,Email,Groups
Test,Example,test12@example.com,All Users|Admin|Test
Test,Example,test13@example.com,All Users
Test,Example,test14@example.com,All Users
Test,Example,test15@example.com,All Users
Test,Example,test16@example.com,All Users
Test,Example,test17@example.com,All Users
First Name,Last Name,Email,User Role,Group
Test,Example,test12@example.com,Admin,Admin|Builder
Test,Example,test13@example.com,Buider,Buider|Test
Test,Example,test14@example.com,End user,End user|Abc
Test,Example,test15@example.com,End user,End user|Abc
Test,Example,test16@example.com,End user,End user|Abc
Test,Example,test17@example.com,End user,End user|Abc
1 First Name Last Name Email Groups User Role Group
2 Test Example test12@example.com All Users|Admin|Test Admin Admin|Builder
3 Test Example test13@example.com All Users Buider Buider|Test
4 Test Example test14@example.com All Users End user End user|Abc
5 Test Example test15@example.com All Users End user End user|Abc
6 Test Example test16@example.com All Users End user End user|Abc
7 Test Example test17@example.com All Users End user End user|Abc

View file

@ -1,251 +1,3 @@
First Name,Last Name,Email,Groups
Test,Example,test12@gmail.com,All Users|Test
Test,Example,test13@gmail.com,All Users
Test,Example,test14@gmail.com,All Users
Test,Example,test15@gmail.com,All Users
Test,Example,test16@gmail.com,All Users
Test,Example,test17@gmail.com,All Users
Test,Example,test18@gmail.com,All Users
Test,Example,test19@gmail.com,All Users
Test,Example,test20@gmail.com,All Users
Test,Example,test21@gmail.com,All Users
Test,Example,test22@gmail.com,All Users
Test,Example,test23@gmail.com,All Users
Test,Example,test24@gmail.com,All Users
Test,Example,test25@gmail.com,All Users
Test,Example,test26@gmail.com,All Users
Test,Example,test27@gmail.com,All Users
Test,Example,test28@gmail.com,All Users
Test,Example,test29@gmail.com,All Users
Test,Example,test30@gmail.com,All Users
Test,Example,test31@gmail.com,All Users
Test,Example,test32@gmail.com,All Users
Test,Example,test33@gmail.com,All Users
Test,Example,test34@gmail.com,All Users
Test,Example,test35@gmail.com,All Users
Test,Example,test36@gmail.com,All Users
Test,Example,test37@gmail.com,All Users
Test,Example,test38@gmail.com,All Users
Test,Example,test39@gmail.com,All Users
Test,Example,test40@gmail.com,All Users
Test,Example,test41@gmail.com,All Users
Test,Example,test42@gmail.com,All Users
Test,Example,test43@gmail.com,All Users
Test,Example,test44@gmail.com,All Users
Test,Example,test45@gmail.com,All Users
Test,Example,test46@gmail.com,All Users
Test,Example,test47@gmail.com,All Users
Test,Example,test48@gmail.com,All Users
Test,Example,test49@gmail.com,All Users
Test,Example,test50@gmail.com,All Users
Test,Example,test51@gmail.com,All Users
Test,Example,test52@gmail.com,All Users
Test,Example,test53@gmail.com,All Users
Test,Example,test54@gmail.com,All Users
Test,Example,test55@gmail.com,All Users
Test,Example,test56@gmail.com,All Users
Test,Example,test57@gmail.com,All Users
Test,Example,test58@gmail.com,All Users
Test,Example,test59@gmail.com,All Users
Test,Example,test60@gmail.com,All Users
Test,Example,test61@gmail.com,All Users
Test,Example,test62@gmail.com,All Users
Test,Example,test63@gmail.com,All Users
Test,Example,test64@gmail.com,All Users
Test,Example,test65@gmail.com,All Users
Test,Example,test66@gmail.com,All Users
Test,Example,test67@gmail.com,All Users
Test,Example,test68@gmail.com,All Users
Test,Example,test69@gmail.com,All Users
Test,Example,test70@gmail.com,All Users
Test,Example,test71@gmail.com,All Users
Test,Example,test72@gmail.com,All Users
Test,Example,test73@gmail.com,All Users
Test,Example,test74@gmail.com,All Users
Test,Example,test75@gmail.com,All Users
Test,Example,test76@gmail.com,All Users
Test,Example,test77@gmail.com,All Users
Test,Example,test78@gmail.com,All Users
Test,Example,test79@gmail.com,All Users
Test,Example,test80@gmail.com,All Users
Test,Example,test81@gmail.com,All Users
Test,Example,test82@gmail.com,All Users
Test,Example,test83@gmail.com,All Users
Test,Example,test84@gmail.com,All Users
Test,Example,test85@gmail.com,All Users
Test,Example,test86@gmail.com,All Users
Test,Example,test87@gmail.com,All Users
Test,Example,test88@gmail.com,All Users
Test,Example,test89@gmail.com,All Users
Test,Example,test90@gmail.com,All Users
Test,Example,test91@gmail.com,All Users
Test,Example,test92@gmail.com,All Users
Test,Example,test93@gmail.com,All Users
Test,Example,test94@gmail.com,All Users
Test,Example,test95@gmail.com,All Users
Test,Example,test96@gmail.com,All Users
Test,Example,test97@gmail.com,All Users
Test,Example,test98@gmail.com,All Users
Test,Example,test99@gmail.com,All Users
Test,Example,test100@gmail.com,All Users
Test,Example,test101@gmail.com,All Users
Test,Example,test102@gmail.com,All Users
Test,Example,test103@gmail.com,All Users
Test,Example,test104@gmail.com,All Users
Test,Example,test105@gmail.com,All Users
Test,Example,test106@gmail.com,All Users
Test,Example,test107@gmail.com,All Users
Test,Example,test108@gmail.com,All Users
Test,Example,test109@gmail.com,All Users
Test,Example,test110@gmail.com,All Users
Test,Example,test111@gmail.com,All Users
Test,Example,test112@gmail.com,All Users
Test,Example,test113@gmail.com,All Users
Test,Example,test114@gmail.com,All Users
Test,Example,test115@gmail.com,All Users
Test,Example,test116@gmail.com,All Users
Test,Example,test117@gmail.com,All Users
Test,Example,test118@gmail.com,All Users
Test,Example,test119@gmail.com,All Users
Test,Example,test120@gmail.com,All Users
Test,Example,test121@gmail.com,All Users
Test,Example,test122@gmail.com,All Users
Test,Example,test123@gmail.com,All Users
Test,Example,test124@gmail.com,All Users
Test,Example,test125@gmail.com,All Users
Test,Example,test126@gmail.com,All Users
Test,Example,test127@gmail.com,All Users
Test,Example,test128@gmail.com,All Users
Test,Example,test129@gmail.com,All Users
Test,Example,test130@gmail.com,All Users
Test,Example,test131@gmail.com,All Users
Test,Example,test132@gmail.com,All Users
Test,Example,test133@gmail.com,All Users
Test,Example,test134@gmail.com,All Users
Test,Example,test135@gmail.com,All Users
Test,Example,test136@gmail.com,All Users
Test,Example,test137@gmail.com,All Users
Test,Example,test138@gmail.com,All Users
Test,Example,test139@gmail.com,All Users
Test,Example,test140@gmail.com,All Users
Test,Example,test141@gmail.com,All Users
Test,Example,test142@gmail.com,All Users
Test,Example,test143@gmail.com,All Users
Test,Example,test144@gmail.com,All Users
Test,Example,test145@gmail.com,All Users
Test,Example,test146@gmail.com,All Users
Test,Example,test147@gmail.com,All Users
Test,Example,test148@gmail.com,All Users
Test,Example,test149@gmail.com,All Users
Test,Example,test150@gmail.com,All Users
Test,Example,test151@gmail.com,All Users
Test,Example,test152@gmail.com,All Users
Test,Example,test153@gmail.com,All Users
Test,Example,test154@gmail.com,All Users
Test,Example,test155@gmail.com,All Users
Test,Example,test156@gmail.com,All Users
Test,Example,test157@gmail.com,All Users
Test,Example,test158@gmail.com,All Users
Test,Example,test159@gmail.com,All Users
Test,Example,test160@gmail.com,All Users
Test,Example,test161@gmail.com,All Users
Test,Example,test162@gmail.com,All Users
Test,Example,test163@gmail.com,All Users
Test,Example,test164@gmail.com,All Users
Test,Example,test165@gmail.com,All Users
Test,Example,test166@gmail.com,All Users
Test,Example,test167@gmail.com,All Users
Test,Example,test168@gmail.com,All Users
Test,Example,test169@gmail.com,All Users
Test,Example,test170@gmail.com,All Users
Test,Example,test171@gmail.com,All Users
Test,Example,test172@gmail.com,All Users
Test,Example,test173@gmail.com,All Users
Test,Example,test174@gmail.com,All Users
Test,Example,test175@gmail.com,All Users
Test,Example,test176@gmail.com,All Users
Test,Example,test177@gmail.com,All Users
Test,Example,test178@gmail.com,All Users
Test,Example,test179@gmail.com,All Users
Test,Example,test180@gmail.com,All Users
Test,Example,test181@gmail.com,All Users
Test,Example,test182@gmail.com,All Users
Test,Example,test183@gmail.com,All Users
Test,Example,test184@gmail.com,All Users
Test,Example,test185@gmail.com,All Users
Test,Example,test186@gmail.com,All Users
Test,Example,test187@gmail.com,All Users
Test,Example,test188@gmail.com,All Users
Test,Example,test189@gmail.com,All Users
Test,Example,test190@gmail.com,All Users
Test,Example,test191@gmail.com,All Users
Test,Example,test192@gmail.com,All Users
Test,Example,test193@gmail.com,All Users
Test,Example,test194@gmail.com,All Users
Test,Example,test195@gmail.com,All Users
Test,Example,test196@gmail.com,All Users
Test,Example,test197@gmail.com,All Users
Test,Example,test198@gmail.com,All Users
Test,Example,test199@gmail.com,All Users
Test,Example,test200@gmail.com,All Users
Test,Example,test201@gmail.com,All Users
Test,Example,test202@gmail.com,All Users
Test,Example,test203@gmail.com,All Users
Test,Example,test204@gmail.com,All Users
Test,Example,test205@gmail.com,All Users
Test,Example,test206@gmail.com,All Users
Test,Example,test207@gmail.com,All Users
Test,Example,test208@gmail.com,All Users
Test,Example,test209@gmail.com,All Users
Test,Example,test210@gmail.com,All Users
Test,Example,test211@gmail.com,All Users
Test,Example,test212@gmail.com,All Users
Test,Example,test213@gmail.com,All Users
Test,Example,test214@gmail.com,All Users
Test,Example,test215@gmail.com,All Users
Test,Example,test216@gmail.com,All Users
Test,Example,test217@gmail.com,All Users
Test,Example,test218@gmail.com,All Users
Test,Example,test219@gmail.com,All Users
Test,Example,test220@gmail.com,All Users
Test,Example,test221@gmail.com,All Users
Test,Example,test222@gmail.com,All Users
Test,Example,test223@gmail.com,All Users
Test,Example,test224@gmail.com,All Users
Test,Example,test225@gmail.com,All Users
Test,Example,test226@gmail.com,All Users
Test,Example,test227@gmail.com,All Users
Test,Example,test228@gmail.com,All Users
Test,Example,test229@gmail.com,All Users
Test,Example,test230@gmail.com,All Users
Test,Example,test231@gmail.com,All Users
Test,Example,test232@gmail.com,All Users
Test,Example,test233@gmail.com,All Users
Test,Example,test234@gmail.com,All Users
Test,Example,test235@gmail.com,All Users
Test,Example,test236@gmail.com,All Users
Test,Example,test237@gmail.com,All Users
Test,Example,test238@gmail.com,All Users
Test,Example,test239@gmail.com,All Users
Test,Example,test240@gmail.com,All Users
Test,Example,test241@gmail.com,All Users
Test,Example,test242@gmail.com,All Users
Test,Example,test243@gmail.com,All Users
Test,Example,test244@gmail.com,All Users
Test,Example,test245@gmail.com,All Users
Test,Example,test246@gmail.com,All Users
Test,Example,test247@gmail.com,All Users
Test,Example,test248@gmail.com,All Users
Test,Example,test249@gmail.com,All Users
Test,Example,test250@gmail.com,All Users
Test,Example,test251@gmail.com,All Users
Test,Example,test252@gmail.com,All Users
Test,Example,test253@gmail.com,All Users
Test,Example,test254@gmail.com,All Users
Test,Example,test255@gmail.com,All Users
Test,Example,test256@gmail.com,All Users
Test,Example,test257@gmail.com,All Users
Test,Example,test258@gmail.com,All Users
Test,Example,test259@gmail.com,All Users
Test,Example,test260@gmail.com,All Users
Test,Example,test261@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
test,test,demo1@gmail.com,Admin,test
test,test,demo2@gmail.com,Builder,abc

1 First Name Last Name Email Groups User Role Group
2 Test test Example test test12@gmail.com demo1@gmail.com All Users|Test Admin test
3 Test test Example test test13@gmail.com demo2@gmail.com All Users Builder abc
Test Example test14@gmail.com All Users
Test Example test15@gmail.com All Users
Test Example test16@gmail.com All Users
Test Example test17@gmail.com All Users
Test Example test18@gmail.com All Users
Test Example test19@gmail.com All Users
Test Example test20@gmail.com All Users
Test Example test21@gmail.com All Users
Test Example test22@gmail.com All Users
Test Example test23@gmail.com All Users
Test Example test24@gmail.com All Users
Test Example test25@gmail.com All Users
Test Example test26@gmail.com All Users
Test Example test27@gmail.com All Users
Test Example test28@gmail.com All Users
Test Example test29@gmail.com All Users
Test Example test30@gmail.com All Users
Test Example test31@gmail.com All Users
Test Example test32@gmail.com All Users
Test Example test33@gmail.com All Users
Test Example test34@gmail.com All Users
Test Example test35@gmail.com All Users
Test Example test36@gmail.com All Users
Test Example test37@gmail.com All Users
Test Example test38@gmail.com All Users
Test Example test39@gmail.com All Users
Test Example test40@gmail.com All Users
Test Example test41@gmail.com All Users
Test Example test42@gmail.com All Users
Test Example test43@gmail.com All Users
Test Example test44@gmail.com All Users
Test Example test45@gmail.com All Users
Test Example test46@gmail.com All Users
Test Example test47@gmail.com All Users
Test Example test48@gmail.com All Users
Test Example test49@gmail.com All Users
Test Example test50@gmail.com All Users
Test Example test51@gmail.com All Users
Test Example test52@gmail.com All Users
Test Example test53@gmail.com All Users
Test Example test54@gmail.com All Users
Test Example test55@gmail.com All Users
Test Example test56@gmail.com All Users
Test Example test57@gmail.com All Users
Test Example test58@gmail.com All Users
Test Example test59@gmail.com All Users
Test Example test60@gmail.com All Users
Test Example test61@gmail.com All Users
Test Example test62@gmail.com All Users
Test Example test63@gmail.com All Users
Test Example test64@gmail.com All Users
Test Example test65@gmail.com All Users
Test Example test66@gmail.com All Users
Test Example test67@gmail.com All Users
Test Example test68@gmail.com All Users
Test Example test69@gmail.com All Users
Test Example test70@gmail.com All Users
Test Example test71@gmail.com All Users
Test Example test72@gmail.com All Users
Test Example test73@gmail.com All Users
Test Example test74@gmail.com All Users
Test Example test75@gmail.com All Users
Test Example test76@gmail.com All Users
Test Example test77@gmail.com All Users
Test Example test78@gmail.com All Users
Test Example test79@gmail.com All Users
Test Example test80@gmail.com All Users
Test Example test81@gmail.com All Users
Test Example test82@gmail.com All Users
Test Example test83@gmail.com All Users
Test Example test84@gmail.com All Users
Test Example test85@gmail.com All Users
Test Example test86@gmail.com All Users
Test Example test87@gmail.com All Users
Test Example test88@gmail.com All Users
Test Example test89@gmail.com All Users
Test Example test90@gmail.com All Users
Test Example test91@gmail.com All Users
Test Example test92@gmail.com All Users
Test Example test93@gmail.com All Users
Test Example test94@gmail.com All Users
Test Example test95@gmail.com All Users
Test Example test96@gmail.com All Users
Test Example test97@gmail.com All Users
Test Example test98@gmail.com All Users
Test Example test99@gmail.com All Users
Test Example test100@gmail.com All Users
Test Example test101@gmail.com All Users
Test Example test102@gmail.com All Users
Test Example test103@gmail.com All Users
Test Example test104@gmail.com All Users
Test Example test105@gmail.com All Users
Test Example test106@gmail.com All Users
Test Example test107@gmail.com All Users
Test Example test108@gmail.com All Users
Test Example test109@gmail.com All Users
Test Example test110@gmail.com All Users
Test Example test111@gmail.com All Users
Test Example test112@gmail.com All Users
Test Example test113@gmail.com All Users
Test Example test114@gmail.com All Users
Test Example test115@gmail.com All Users
Test Example test116@gmail.com All Users
Test Example test117@gmail.com All Users
Test Example test118@gmail.com All Users
Test Example test119@gmail.com All Users
Test Example test120@gmail.com All Users
Test Example test121@gmail.com All Users
Test Example test122@gmail.com All Users
Test Example test123@gmail.com All Users
Test Example test124@gmail.com All Users
Test Example test125@gmail.com All Users
Test Example test126@gmail.com All Users
Test Example test127@gmail.com All Users
Test Example test128@gmail.com All Users
Test Example test129@gmail.com All Users
Test Example test130@gmail.com All Users
Test Example test131@gmail.com All Users
Test Example test132@gmail.com All Users
Test Example test133@gmail.com All Users
Test Example test134@gmail.com All Users
Test Example test135@gmail.com All Users
Test Example test136@gmail.com All Users
Test Example test137@gmail.com All Users
Test Example test138@gmail.com All Users
Test Example test139@gmail.com All Users
Test Example test140@gmail.com All Users
Test Example test141@gmail.com All Users
Test Example test142@gmail.com All Users
Test Example test143@gmail.com All Users
Test Example test144@gmail.com All Users
Test Example test145@gmail.com All Users
Test Example test146@gmail.com All Users
Test Example test147@gmail.com All Users
Test Example test148@gmail.com All Users
Test Example test149@gmail.com All Users
Test Example test150@gmail.com All Users
Test Example test151@gmail.com All Users
Test Example test152@gmail.com All Users
Test Example test153@gmail.com All Users
Test Example test154@gmail.com All Users
Test Example test155@gmail.com All Users
Test Example test156@gmail.com All Users
Test Example test157@gmail.com All Users
Test Example test158@gmail.com All Users
Test Example test159@gmail.com All Users
Test Example test160@gmail.com All Users
Test Example test161@gmail.com All Users
Test Example test162@gmail.com All Users
Test Example test163@gmail.com All Users
Test Example test164@gmail.com All Users
Test Example test165@gmail.com All Users
Test Example test166@gmail.com All Users
Test Example test167@gmail.com All Users
Test Example test168@gmail.com All Users
Test Example test169@gmail.com All Users
Test Example test170@gmail.com All Users
Test Example test171@gmail.com All Users
Test Example test172@gmail.com All Users
Test Example test173@gmail.com All Users
Test Example test174@gmail.com All Users
Test Example test175@gmail.com All Users
Test Example test176@gmail.com All Users
Test Example test177@gmail.com All Users
Test Example test178@gmail.com All Users
Test Example test179@gmail.com All Users
Test Example test180@gmail.com All Users
Test Example test181@gmail.com All Users
Test Example test182@gmail.com All Users
Test Example test183@gmail.com All Users
Test Example test184@gmail.com All Users
Test Example test185@gmail.com All Users
Test Example test186@gmail.com All Users
Test Example test187@gmail.com All Users
Test Example test188@gmail.com All Users
Test Example test189@gmail.com All Users
Test Example test190@gmail.com All Users
Test Example test191@gmail.com All Users
Test Example test192@gmail.com All Users
Test Example test193@gmail.com All Users
Test Example test194@gmail.com All Users
Test Example test195@gmail.com All Users
Test Example test196@gmail.com All Users
Test Example test197@gmail.com All Users
Test Example test198@gmail.com All Users
Test Example test199@gmail.com All Users
Test Example test200@gmail.com All Users
Test Example test201@gmail.com All Users
Test Example test202@gmail.com All Users
Test Example test203@gmail.com All Users
Test Example test204@gmail.com All Users
Test Example test205@gmail.com All Users
Test Example test206@gmail.com All Users
Test Example test207@gmail.com All Users
Test Example test208@gmail.com All Users
Test Example test209@gmail.com All Users
Test Example test210@gmail.com All Users
Test Example test211@gmail.com All Users
Test Example test212@gmail.com All Users
Test Example test213@gmail.com All Users
Test Example test214@gmail.com All Users
Test Example test215@gmail.com All Users
Test Example test216@gmail.com All Users
Test Example test217@gmail.com All Users
Test Example test218@gmail.com All Users
Test Example test219@gmail.com All Users
Test Example test220@gmail.com All Users
Test Example test221@gmail.com All Users
Test Example test222@gmail.com All Users
Test Example test223@gmail.com All Users
Test Example test224@gmail.com All Users
Test Example test225@gmail.com All Users
Test Example test226@gmail.com All Users
Test Example test227@gmail.com All Users
Test Example test228@gmail.com All Users
Test Example test229@gmail.com All Users
Test Example test230@gmail.com All Users
Test Example test231@gmail.com All Users
Test Example test232@gmail.com All Users
Test Example test233@gmail.com All Users
Test Example test234@gmail.com All Users
Test Example test235@gmail.com All Users
Test Example test236@gmail.com All Users
Test Example test237@gmail.com All Users
Test Example test238@gmail.com All Users
Test Example test239@gmail.com All Users
Test Example test240@gmail.com All Users
Test Example test241@gmail.com All Users
Test Example test242@gmail.com All Users
Test Example test243@gmail.com All Users
Test Example test244@gmail.com All Users
Test Example test245@gmail.com All Users
Test Example test246@gmail.com All Users
Test Example test247@gmail.com All Users
Test Example test248@gmail.com All Users
Test Example test249@gmail.com All Users
Test Example test250@gmail.com All Users
Test Example test251@gmail.com All Users
Test Example test252@gmail.com All Users
Test Example test253@gmail.com All Users
Test Example test254@gmail.com All Users
Test Example test255@gmail.com All Users
Test Example test256@gmail.com All Users
Test Example test257@gmail.com All Users
Test Example test258@gmail.com All Users
Test Example test259@gmail.com All Users
Test Example test260@gmail.com All Users
Test Example test261@gmail.com All Users

View file

@ -1,6 +1,4 @@
First Name,Last Name,Email,Groups
Test,Example,test12@gmail.com,All Users
Test,Example,test12@gmail.com,All Users
Test,Example,test14@gmail.com,All Users
Test,Example,test14@gmail.com,All Users
Test,Example,test16@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
test,test,demo11@gmail.com,Admin,
test,test,demo11@gmail.com,Builder,
test,test,demo12@gmail.com,Builder,

1 First Name Last Name Email Groups User Role Group
2 Test test Example test test12@gmail.com demo11@gmail.com All Users Admin
3 Test test Example test test12@gmail.com demo11@gmail.com All Users Builder
4 Test test Example test test14@gmail.com demo12@gmail.com All Users Builder
Test Example test14@gmail.com All Users
Test Example test16@gmail.com All Users

View file

@ -1,12 +1,11 @@
First Name,Last Name,Email,Groups
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
Test,Example,,All Users
First Name,Last Name,Email,User Role,Group
test,test,,Admin,Admin
test,test,,Builder,Builder
test,test,,Builder,Builder
test,test,,End User,End User
test,test,,End User,End User
test,test,,End User,End User
test,test,,End User,End User
test,test,,End User,End User
test,test,,End User,End User
test,test,,End User,End User
1 First Name Last Name Email Groups User Role Group
2 Test test Example test All Users Admin Admin
3 Test test Example test All Users Builder Builder
4 Test test Example test All Users Builder Builder
5 Test test Example test All Users End User End User
6 Test test Example test All Users End User End User
7 Test test Example test All Users End User End User
8 Test test Example test All Users End User End User
9 Test test Example test All Users End User End User
10 Test test Example test All Users End User End User
11 Test test Example test All Users End User End User
Test Example All Users

View file

@ -1,6 +1,4 @@
First Name,Last Name,Email,Groups
,Example,test12withoutfirstname@gmail.com,All Users
,Example,test13withoutfirstname@gmail.com,All Users
,Example,test14withoutfirstname@gmail.com,All Users
,Example,test15withoutfirstname@gmail.com,All Users
,Example,test16withoutfirstname@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
,test,demo1@gmail.com,Admin,
,test,demo2@gmail.com,Builder,
,test,demo3@gmail.com,End User,

1 First Name Last Name Email Groups User Role Group
2 Example test test12withoutfirstname@gmail.com demo1@gmail.com All Users Admin
3 Example test test13withoutfirstname@gmail.com demo2@gmail.com All Users Builder
4 Example test test14withoutfirstname@gmail.com demo3@gmail.com All Users End User
Example test15withoutfirstname@gmail.com All Users
Example test16withoutfirstname@gmail.com All Users

View file

@ -1,6 +1,6 @@
First Name,Last Name,Email,Groups
Test,Example,test12@gmail.com,
Test,Example,test13@gmail.com,
Test,Example,test14@gmail.com,
Test,Example,test15@gmail.com,
Test,Example,test16@gmail.com,
First Name,Last Name,Email,User Role,Group
Test,Example,test12@gmail.com,Admin,
Test,Example,test13@gmail.com,Builder,
Test,Example,test14@gmail.com,End User,
Test,Example,test15@gmail.com,End User,
Test,Example,test16@gmail.com,End User,
1 First Name Last Name Email Groups User Role Group
2 Test Example test12@gmail.com Admin
3 Test Example test13@gmail.com Builder
4 Test Example test14@gmail.com End User
5 Test Example test15@gmail.com End User
6 Test Example test16@gmail.com End User

View file

@ -1,6 +1,11 @@
First Name,Last Name,Email,Groups
Test,,test12withoutlastname@gmail.com,All Users
Test,,test13withoutlastname@gmail.com,All Users
Test,,test14withoutlastname@gmail.com,All Users
Test,,test15withoutlastname@gmail.com,All Users
Test,,test16withoutlastname@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
test,,withoutlastname1@gmail.com,Admin,Admin
test,,withoutlastname2@gmail.com,Builder,Builder
test,,withoutlastname3@gmail.com,Builder,Builder
test,,withoutlastname4@gmail.com,End User,End User
test,,withoutlastname5@gmail.com,End User,End User
test,,withoutlastname6@gmail.com,End User,End User
test,,withoutlastname7@gmail.com,End User,End User
test,,withoutlastname8@gmail.com,End User,End User
test,,withoutlastname9@gmail.com,End User,End User
test,,withoutlastname10@gmail.com,End User,End User
1 First Name Last Name Email Groups User Role Group
2 Test test test12withoutlastname@gmail.com withoutlastname1@gmail.com All Users Admin Admin
3 Test test test13withoutlastname@gmail.com withoutlastname2@gmail.com All Users Builder Builder
4 Test test test14withoutlastname@gmail.com withoutlastname3@gmail.com All Users Builder Builder
5 Test test test15withoutlastname@gmail.com withoutlastname4@gmail.com All Users End User End User
6 Test test test16withoutlastname@gmail.com withoutlastname5@gmail.com All Users End User End User
7 test withoutlastname6@gmail.com End User End User
8 test withoutlastname7@gmail.com End User End User
9 test withoutlastname8@gmail.com End User End User
10 test withoutlastname9@gmail.com End User End User
11 test withoutlastname10@gmail.com End User End User

View file

@ -1,12 +1,11 @@
First Name,Last Name,Email,Groups
,,test12@gmail.com,All Users
,,test13@gmail.com,All Users
,,test14@gmail.com,All Users
,,test15@gmail.com,All Users
,,test16@gmail.com,All Users
,,test17@gmail.com,All Users
,,test18@gmail.com,All Users
,,test19@gmail.com,All Users
,,test20@gmail.com,All Users
,,test21@gmail.com,All Users
,,test22@gmail.com,All Users
First Name,Last Name,Email,User Role,Group
,,withoutname1@gmail.com,Admin,Admin
,,withoutname2@gmail.com,Builder,Builder
,,withoutname3@gmail.com,Builder,Builder
,,withoutname4@gmail.com,End User,End User
,,withoutname5@gmail.com,End User,End User
,,withoutname6@gmail.com,End User,End User
,,withoutname7@gmail.com,End User,End User
,,withoutname8@gmail.com,End User,End User
,,withoutname9@gmail.com,End User,End User
,,withoutname10@gmail.com,End User,End User
1 First Name Last Name Email Groups User Role Group
2 test12@gmail.com withoutname1@gmail.com All Users Admin Admin
3 test13@gmail.com withoutname2@gmail.com All Users Builder Builder
4 test14@gmail.com withoutname3@gmail.com All Users Builder Builder
5 test15@gmail.com withoutname4@gmail.com All Users End User End User
6 test16@gmail.com withoutname5@gmail.com All Users End User End User
7 test17@gmail.com withoutname6@gmail.com All Users End User End User
8 test18@gmail.com withoutname7@gmail.com All Users End User End User
9 test19@gmail.com withoutname8@gmail.com All Users End User End User
10 test20@gmail.com withoutname9@gmail.com All Users End User End User
11 test21@gmail.com withoutname10@gmail.com All Users End User End User
test22@gmail.com All Users

View file

@ -11,9 +11,9 @@ import {
export const login = () => {
cy.visit("/");
cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.loginButton).click();
cy.clearAndType(onboardingSelectors.emailInput, "dev@tooljet.io");
cy.clearAndType(onboardingSelectors.passwordInput, "password");
cy.get(onboardingSelectors.signInButton).click();
};
export const modifyAndVerifyAppCardIcon = (appName) => {

View file

@ -235,18 +235,18 @@ export const workspaceLoginPageElements = (workspaceName) => {
};
export const passwordLoginVisible = () => {
cy.get(commonSelectors.workEmailInputField).should("be.visible");
cy.get(commonSelectors.passwordInputField).should("be.visible");
cy.get(commonSelectors.loginButton).verifyVisibleElement(
cy.get(onboardingSelectors.emailInput).should("be.visible");
cy.get(onboardingSelectors.passwordInput).should("be.visible");
cy.get(onboardingSelectors.signInButton).verifyVisibleElement(
"have.text",
commonText.loginButton
);
};
export const workspaceLogin = (workspaceName) => {
cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.loginButton).click();
cy.clearAndType(onboardingSelectors.emailInput, "dev@tooljet.io");
cy.clearAndType(onboardingSelectors.passwordInput, "password");
cy.get(onboardingSelectors.signInButton).click();
cy.wait(2000);
cy.get(commonSelectors.homePageLogo).should("be.visible");
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
@ -295,13 +295,13 @@ export const signInPageElements = () => {
"have.text",
commonText.forgotPasswordLink
);
cy.get(commonSelectors.loginButton).verifyVisibleElement(
cy.get(onboardingSelectors.signInButton).verifyVisibleElement(
"have.text",
commonText.loginButton
);
cy.get(commonSelectors.workEmailInputField).should("be.visible");
cy.get(commonSelectors.passwordInputField).should("be.visible");
cy.get(onboardingSelectors.emailInput).should("be.visible");
cy.get(onboardingSelectors.passwordInput).should("be.visible");
cy.get("body").then(($el) => {
if ($el.text().includes("Google")) {
@ -477,7 +477,7 @@ export const invitePageElements = () => {
"have.text",
commonText.passwordLabel
);
cy.get(commonSelectors.passwordInputField).should("be.visible");
cy.get(onboardingSelectors.passwordInput).should("be.visible");
cy.get(commonSelectors.acceptInviteButton).verifyVisibleElement(
"have.text",
commonText.acceptInviteButton

View file

@ -6,6 +6,8 @@ import { ssoSelector } from "Selectors/manageSSO";
import { ssoText } from "Texts/manageSSO";
import * as common from "Support/utils/common";
import { commonText } from "Texts/common";
import { onboardingSelectors } from "Selectors/onboarding";
export const manageUsersElements = () => {
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
@ -150,19 +152,19 @@ export const manageUsersElements = () => {
export const inviteUser = (firstName, email) => {
cy.userInviteApi(firstName, email);
fetchAndVisitInviteLink(email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.clearAndType(onboardingSelectors.passwordInput, "password");
cy.get(commonSelectors.acceptInviteButton).click();
};
export const confirmInviteElements = (email) => {
cy.get(commonSelectors.SignUpSectionHeader).verifyVisibleElement(
cy.get(commonSelectors.signUpSectionHeader).verifyVisibleElement(
"have.text", "Sign up");
cy.get('[data-cy="workspace-signup-header"]').verifyVisibleElement(
"have.text", "Sign up to the workspace - My workspace");
cy.get('[data-cy="signup-info"]').verifyVisibleElement(
"have.text", "Sign up to the workspace - My workspace. ");
cy.verifyLabel("Email")
cy.verifyLabel("Create a password")
// cy.verifyLabel("Email")
// cy.verifyLabel("Create a password")
cy.get(commonSelectors.invitedUserEmail).verifyVisibleElement(
"have.text", email);
@ -215,7 +217,6 @@ export const bulkUserUpload = (file, fileName, toastMessage) => {
.should("be.visible")
.and("have.text", toastMessage);
cy.get(usersSelector.toastCloseButton).click();
cy.wait(200);
};
@ -242,8 +243,8 @@ export const copyInvitationLink = (firstName, email) => {
export const fillUserInviteForm = (firstName, email) => {
cy.get(usersSelector.buttonAddUsers).click();
cy.clearAndType(commonSelectors.inputFieldFullName, firstName);
cy.clearAndType(commonSelectors.inputFieldEmailAddress, email);
cy.clearAndType(onboardingSelectors.nameInput, firstName);
cy.clearAndType(onboardingSelectors.signupEmailInput, email);
};
export const selectUserGroup = (groupName) => {
@ -293,7 +294,8 @@ export const inviteUserWithUserGroups = (
cy.wait(1000);
fetchAndVisitInviteLink(email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.wait(2000);
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
// cy.intercept('GET', '/api/organizations').as('org')
cy.get(commonSelectors.signUpButton).click();
cy.wait(2000);
@ -372,7 +374,7 @@ export const inviteUserWithUserRole = (
cy.wait(1000);
fetchAndVisitInviteLink(email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
cy.get(commonSelectors.signUpButton).click();
cy.wait(2000);
cy.get(commonSelectors.acceptInviteButton).click();

View file

@ -8,11 +8,12 @@ import {
import { navigateToManageUsers, logout } from "Support/utils/common";
import { ssoSelector } from "Selectors/manageSSO";
import { ssoText } from "Texts/manageSSO";
import { onboardingSelectors } from "Selectors/onboarding";
export const verifyConfirmEmailPage = (email) => {
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.emailImage).should("be.visible");
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
cy.get('[data-cy="check-your-mail-header"]').verifyVisibleElement(
"have.text",
commonText.emailPageHeader
);
@ -31,32 +32,17 @@ export const verifyConfirmEmailPage = (email) => {
"have.text",
commonText.onboardingSeperatorText
);
cy.get(commonSelectors.resendEmailButton).should("be.visible");
cy.get(commonSelectors.editEmailButton).verifyVisibleElement(
cy.get('[data-cy="back-to-signup"]').verifyVisibleElement(
"have.text",
commonText.editEmailButton
"Back to sign up"
);
};
export const verifyConfirmPageElements = () => {
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.emailImage).should("be.visible");
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
commonText.emailVerifiedText
);
cy.get(commonSelectors.onboardingPageDescription).verifyVisibleElement(
"have.text",
commonText.continueToSetUp
);
cy.get(commonSelectors.setUpToolJetButton).verifyVisibleElement(
"have.text",
commonText.setUpToolJetButton
);
};
export const verifyOnboardingQuestions = (fullName, workspaceName) => {
cy.wait(5000);
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.userAccountNameAvatar).should("be.visible");
cy.get(commonSelectors.createAccountCheckMark).should("be.visible");
@ -125,7 +111,7 @@ export const verifyOnboardingQuestions = (fullName, workspaceName) => {
export const verifyInvalidInvitationLink = () => {
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.emailImage).should("be.visible");
// cy.get(commonSelectors.emailImage).should("be.visible");
cy.get(commonSelectors.onboardingPageHeader).verifyVisibleElement(
"have.text",
@ -136,20 +122,24 @@ export const verifyInvalidInvitationLink = () => {
commonText.inalidInvitationLinkDescription
);
cy.get(commonSelectors.backtoSignUpButton).verifyVisibleElement(
"have.text",
commonText.backtoSignUpButton
);
// cy.get(commonSelectors.backtoSignUpButton).verifyVisibleElement(
// "have.text",
// commonText.backtoSignUpButton
// );
};
export const userSignUp = (fullName, email, workspaceName) => {
let invitationLink;
cy.intercept("GET", "/api/organizations/public-configs").as("publicConfig");
cy.visit("/");
cy.wait(1000);
cy.get(commonSelectors.createAnAccountLink).realClick();
cy.clearAndType(commonSelectors.nameInputField, fullName);
cy.clearAndType(commonSelectors.emailInputField, email);
cy.clearAndType(commonSelectors.passwordInputField, commonText.password);
cy.wait("@publicConfig"); // Wait for the API response
cy.get(commonSelectors.createAnAccountLink).realClick(); // Proceed to click the link
cy.get(onboardingSelectors.nameInput).should('not.be.disabled');
cy.wait(3000)
cy.get(onboardingSelectors.nameInput).clear();
cy.get(onboardingSelectors.nameInput).type(fullName);
cy.clearAndType(onboardingSelectors.emailInput, email);
cy.clearAndType(onboardingSelectors.passwordInput, commonText.password);
cy.get(commonSelectors.signUpButton).click();
cy.wait(500);
@ -159,10 +149,9 @@ export const userSignUp = (fullName, email, workspaceName) => {
}).then((resp) => {
invitationLink = `/invitations/${resp.rows[0].invitation_token}`;
cy.visit(invitationLink);
cy.get(commonSelectors.setUpToolJetButton).click();
cy.wait(4000);
verifyOnboardingQuestions(fullName, workspaceName);
updateWorkspaceName(email, workspaceName);
cy.clearAndType('[data-cy="onboarding-workspace-name-input"]', workspaceName)
cy.get('[data-cy="onboarding-submit-button"]').click();
});
};
@ -211,10 +200,10 @@ export const inviteUser = (firstName, email) => {
cy.userInviteApi(firstName, email);
fetchAndVisitInviteLink(email);
cy.wait(1000);
cy.get(commonSelectors.passwordInputField).should("be.visible");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(onboardingSelectors.loginPasswordInput).should("be.visible");
cy.clearAndType(onboardingSelectors.loginPasswordInput, "password");
// cy.intercept("GET", "/api/organizations").as("org");
cy.get(commonSelectors.signUpButton).click();
cy.get(commonSelectors.continueButton).click();
cy.wait(2000);
cy.get(commonSelectors.acceptInviteButton).click();
};
@ -222,7 +211,7 @@ export const inviteUser = (firstName, email) => {
export const addNewUser = (firstName, email) => {
navigateToManageUsers();
inviteUser(firstName, email);
updateWorkspaceName(email);
// updateWorkspaceName(email);
};
export const updateWorkspaceName = (email, workspaceName = email) => {
@ -300,19 +289,32 @@ export const visitWorkspaceInvitation = (email, workspaceName) => {
export const SignUpPageElements = () => {
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.SignUpSectionHeader).verifyVisibleElement(
cy.get(commonSelectors.signUpSectionHeader).verifyVisibleElement(
"have.text",
"Sign up"
);
cy.get(commonSelectors.signUpButton).verifyVisibleElement(
"have.text",
commonText.getStartedButton
"Sign up"
);
cy.get(commonSelectors.signInRedirectText).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
commonText.signInRedirectText
);
});
// cy.get('[data-cy="signup-info"]').should(($el) => {
// expect($el.contents().first().text().trim()).to.eq(
// commonText.signInRedirectText
// );
// });
cy.get(onboardingSelectors.signupNameLabel).verifyVisibleElement("have.text", "Name *");
cy.get(onboardingSelectors.nameInput).should('be.visible');
cy.get(onboardingSelectors.emailLabel).verifyVisibleElement(
"have.text",
"Email *"
);
// cy.get(commonSelectors.loginPasswordLabel).verifyVisibleElement("have.text", "Password *");
cy.get(onboardingSelectors.loginPasswordInput).should("be.visible");
cy.get(commonSelectors.signInRedirectLink).verifyVisibleElement(
"have.text",
commonText.signInRedirectLink
@ -357,5 +359,6 @@ export const signUpLink = (email) => {
}).then((resp) => {
invitationLink = `/invitations/${resp.rows[0].invitation_token}`;
cy.visit(invitationLink);
cy.wait(3000);
});
}

View file

@ -3,27 +3,27 @@ import { commonText } from "Texts/common";
export const selfHostCommonElements = () => {
cy.get(commonSelectors.pageLogo).should("be.visible");
cy.get(commonSelectors.setUpadminCheckPoint).verifyVisibleElement(
"have.text",
commonText.setUpadminCheckPoint
);
// cy.get(commonSelectors.setUpadminCheckPoint).verifyVisibleElement(
// "have.text",
// commonText.setUpadminCheckPoint
// );
cy.get(commonSelectors.setUpworkspaceCheckPoint).verifyVisibleElement(
"have.text",
commonText.setUpworkspaceCheckPoint
);
cy.get(commonSelectors.companyProfileCheckPoint).verifyVisibleElement(
"have.text",
commonText.companyProfileCheckPoint
);
cy.get(commonSelectors.onboardingPageSubHeader).verifyVisibleElement(
"have.text",
commonText.onboardingPageSubHeader
);
cy.get(commonSelectors.continueButton).verifyVisibleElement(
// cy.get(commonSelectors.companyProfileCheckPoint).verifyVisibleElement(
// "have.text",
// commonText.companyProfileCheckPoint
// );
// cy.get(commonSelectors.onboardingPageSubHeader).verifyVisibleElement(
// "have.text",
// commonText.onboardingPageSubHeader
// );
cy.get(commonSelectors.OnbordingContinue).verifyVisibleElement(
"have.text",
commonText.continueButton
);
cy.get(commonSelectors.continueButton).should("be.disabled");
// cy.get(commonSelectors.OnbordingContinue).should("be.disabled");
};
export const commonElementsWorkspaceSetup = () => {

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
"@cypress/code-coverage": "^3.12.12",
"@cypress/webpack-preprocessor": "^5.12.0",
"@faker-js/faker": "^7.3.0",
"cypress": "^12.5.1"
"cypress": "^13.16.0"
},
"dependencies": {
"cypress-real-events": "^1.7.6",

View file

@ -1 +1 @@
3.2.4-ce
3.2.0-ce

View file

@ -0,0 +1,9 @@
<svg width="13" height="12" viewBox="0 0 13 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.26139 5.99998C5.20537 7.02317 6.17589 8.16244 6.89354 11C7.61119 8.16244 8.5817 7.02317 11.5257 5.99998C8.5817 4.97686 7.61119 3.83759 6.89354 1C6.17589 3.83759 5.20537 4.97686 2.26139 5.99998Z" fill="url(#paint0_linear_559_384)"/>
<defs>
<linearGradient id="paint0_linear_559_384" x1="12.4652" y1="-5.5" x2="0.807046" y2="-4.34623" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF5F6D"/>
<stop offset="1" stop-color="#FFC371"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 575 B

View file

@ -279,6 +279,12 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
if (isEmpty(selectableDataSources)) {
return '';
}
const isSampleDb = selectedDataSource?.type === DATA_SOURCE_TYPE.SAMPLE;
const docLink = isSampleDb
? 'https://docs.tooljet.com/docs/data-sources/sample-data-sources'
: selectedDataSource?.pluginId && selectedDataSource.pluginId.trim() !== ''
? `https://docs.tooljet.com/docs/marketplace/plugins/marketplace-plugin-${selectedDataSource?.kind}/`
: `https://docs.tooljet.com/docs/data-sources/${selectedDataSource?.kind}`;
return (
<>
<div className="" ref={paramListContainerRef}>
@ -299,7 +305,7 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
>
Source
</div>
<div className="d-flex align-items-end" style={{ width: '364px' }}>
<div className="d-flex flex-column align-items-start" style={{ width: '500px' }}>
<ChangeDataSource
dataSources={selectableDataSources}
value={selectedDataSource}
@ -307,6 +313,18 @@ export const QueryManagerBody = ({ darkMode, options, setOptions, activeTab }) =
changeDataQuery(newDataSource);
}}
/>
<div>
{`To know more about querying ${selectedDataSource?.kind} data,`}
&nbsp;
<a
href={docLink}
target="_blank"
style={{ marginLeft: '0px !important', color: 'hsl(226, 70.0%, 55.5%)', textDecoration: 'underline' }}
rel="noreferrer"
>
{t('globals.readDocumentation', 'read documentation').toLowerCase()}
</a>
</div>
</div>
</div>
</>

View file

@ -3,12 +3,13 @@ import TabContent from './TabContent';
export default ({
options = [],
jsonBody,
jsonBody, // FIXME: Remove this once data migration to raw_body is complete
rawBody,
theme,
removeKeyValuePair,
addNewKeyValuePair,
onChange,
onJsonBodyChange,
onRawBodyChange,
componentName,
bodyToggle,
}) => {
@ -19,10 +20,11 @@ export default ({
theme={theme}
removeKeyValuePair={removeKeyValuePair}
onChange={onChange}
onJsonBodyChange={onJsonBodyChange}
onRawBodyChange={onRawBodyChange}
componentName={componentName}
tabType={'body'}
jsonBody={jsonBody}
jsonBody={jsonBody} // FIXME: Remove this once data migration to raw_body is complete
rawBody={rawBody}
paramType={'body'}
bodyToggle={bodyToggle}
addNewKeyValuePair={addNewKeyValuePair}

View file

@ -12,8 +12,9 @@ export default ({
options = [],
theme,
onChange,
jsonBody,
onJsonBodyChange,
jsonBody, // FIXME: Remove this once data migration to raw_body is complete
rawBody,
onRawBodyChange,
componentName,
removeKeyValuePair,
paramType,
@ -86,11 +87,10 @@ export default ({
<div>
<CodeHinter
type="extendedSingleLine"
initialValue={jsonBody ?? ''}
lang="javascript"
initialValue={(rawBody || jsonBody) ?? ''} // If raw_body is not set, set initial value to legacy json_body if present
height={'300px'}
className="query-hinter"
onChange={(value) => onJsonBodyChange(value)}
onChange={(value) => onRawBodyChange(value)}
componentName={`${componentName}/${tabType}`}
/>
</div>

View file

@ -10,7 +10,7 @@ function ControlledTabs({
options,
theme,
onChange,
onJsonBodyChange,
onRawBodyChange,
removeKeyValuePair,
addNewKeyValuePair,
darkMode,
@ -34,7 +34,7 @@ function ControlledTabs({
</ListGroup>
{key === 'body' && (
<div className="text-nowrap d-flex align-items-center">
Raw JSON&nbsp;&nbsp;
Raw &nbsp;&nbsp;
<CustomToggleSwitch
toggleSwitchFunction={setBodyToggle}
action="bodyToggle"
@ -78,9 +78,10 @@ function ControlledTabs({
removeKeyValuePair={removeKeyValuePair}
addNewKeyValuePair={addNewKeyValuePair}
onChange={onChange}
onJsonBodyChange={onJsonBodyChange}
onRawBodyChange={onRawBodyChange}
options={options['body']}
jsonBody={options['json_body']}
jsonBody={options['json_body']} // FIXME: Remove this once data migration to raw_body is complete
rawBody={options['raw_body']}
theme={theme}
bodyToggle={bodyToggle}
darkMode={darkMode}

View file

@ -15,7 +15,15 @@ class Restapi extends React.Component {
super(props);
const options = defaults(
{ ...props.options },
{ headers: [['', '']], url_params: [], body: [], json_body: null, body_toggle: false, cookies: [['', '']] }
{
headers: [['', '']],
url_params: [],
body: [],
json_body: null, // FIXME: Remove this once data migration to raw_body is complete
raw_body: null,
body_toggle: false,
cookies: [['', '']],
}
);
this.state = {
@ -117,9 +125,16 @@ class Restapi extends React.Component {
});
};
handleJsonBodyChanged = (jsonBody) => {
handleRawBodyChanged = (rawBody) => {
const { options } = deepClone(this.state);
options['json_body'] = jsonBody;
// If this is the first time raw_body is set, nullify json_body for data migration
// FIXME: Remove this if condition once data migration to raw_body is complete
if (!options['raw_body'] && options['json_body']) {
options['json_body'] = null;
}
options['raw_body'] = rawBody;
this.setState({ options }, () => {
this.props.optionsChanged(options);
@ -188,7 +203,7 @@ class Restapi extends React.Component {
</p>
</div>
<div className={`me-2`} style={{ width: '90px', height: '32px' }}>
<label className="font-weight-medium color-slate12">Method</label>
<label className="font-weight-bold color-slate12">Method</label>
<Select
options={[
{ label: 'GET', value: 'get' },
@ -211,7 +226,7 @@ class Restapi extends React.Component {
</div>
<div className={`field w-100 rest-methods-url`}>
<div className="font-weight-medium color-slate12">URL</div>
<div className="font-weight-bold color-slate12">URL</div>
<div className="d-flex">
{dataSourceURL && (
<BaseUrl theme={this.props.darkMode ? 'monokai' : 'default'} dataSourceURL={dataSourceURL} />
@ -237,7 +252,7 @@ class Restapi extends React.Component {
theme={this.props.darkMode ? 'monokai' : 'default'}
options={this.state.options}
onChange={this.handleChange}
onJsonBodyChange={this.handleJsonBodyChanged}
onRawBodyChange={this.handleRawBodyChanged}
removeKeyValuePair={this.removeKeyValuePair}
addNewKeyValuePair={this.addNewKeyValuePair}
darkMode={this.props.darkMode}

View file

@ -1,392 +0,0 @@
import React from 'react';
// import 'codemirror/theme/duotone-light.css';
import DOMPurify from 'dompurify';
import Select from '@/_ui/Select';
import { openapiService } from '@/_services';
import { withTranslation } from 'react-i18next';
import { queryManagerSelectComponentStyle } from '@/_ui/Select/styles';
import CodeHinter from '@/AppBuilder/CodeEditor';
const operationColorMapping = {
get: 'azure',
post: 'green',
delete: 'red',
put: 'yellow',
};
class StripeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
loadingSpec: true,
};
}
componentDidUpdate(prevProps) {
if (prevProps.options.parameters !== this.props.options.parameters) {
this.setState({
options: {
...this.state.options,
parameters: this.props.options.parameters,
},
});
}
}
componentDidMount() {
const queryParams = {
path: this.props.options?.params?.path ?? {},
query: this.props.options?.params?.query ?? {},
request: this.props.options?.params?.request ?? {},
};
this.setState({
loadingSpec: true,
options: {
...this.props.options,
params: queryParams,
},
});
this.fetchOpenApiSpec();
}
fetchOpenApiSpec = () => {
this.setState({ loadingSpec: true });
openapiService
.fetchSpecFromUrl('https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json')
.then((response) => {
response.text().then((text) => {
const data = JSON.parse(text);
this.setState({ specJson: data, loadingSpec: false });
});
});
};
changeOption(option, value) {
this.setState({
options: {
...this.state.options,
[option]: value,
},
});
}
changeOperation = (value) => {
const operation = value.split(',')[0];
const path = value.split(',')[1];
this.setState(
{
options: {
...this.state.options,
path,
operation,
selectedOperation: this.state.specJson.paths[path][operation],
},
},
() => {
this.props.optionsChanged(this.state.options);
}
);
};
changeParam = (paramType, paramName, value) => {
const options = this.state.options;
const newOptions = {
...options,
params: {
...options.params,
[paramType]: {
...options.params[paramType],
[paramName]: value,
},
},
};
this.setState({
options: newOptions,
});
this.props.optionsChanged(newOptions);
};
removeParam = (paramType, paramName) => {
const newOptions = JSON.parse(JSON.stringify(this.state.options));
newOptions['params'][paramType][paramName] = undefined;
this.setState(
{
options: newOptions,
},
() => {
this.props.optionsChanged(newOptions);
}
);
};
renderOperationOption = (props) => {
const path = props.value;
const operation = props.label;
if (path && operation) {
return (
<div className="row">
<div className="col-auto" style={{ width: '60px' }}>
<span className={`badge bg-${operationColorMapping[operation]}`}>{operation}</span>
</div>
<div className="col">
<span>{path}</span>
</div>
</div>
);
} else {
return 'Select an operation';
}
};
computeOperationSelectionOptions = (operationOptions) => {
let options = [];
const paths = operationOptions?.paths;
if (paths) {
for (const path of Object.keys(paths)) {
for (const operation of Object.keys(paths[path])) {
options.push({
value: `${operation},${path}`,
name: path,
operation: operation,
});
}
}
}
return options;
};
render() {
const { options, specJson, loadingSpec } = this.state;
const selectedOperation = options?.selectedOperation;
let pathParams = [];
let queryParams = [];
let requestBody = [];
if (selectedOperation) {
if (selectedOperation.parameters) {
pathParams = selectedOperation.parameters.filter((param) => param.in === 'path');
queryParams = selectedOperation.parameters.filter((param) => param.in === 'query');
}
if (selectedOperation.requestBody) {
const requestType = Object.keys(selectedOperation.requestBody.content)[0];
requestBody = selectedOperation.requestBody.content[requestType];
}
}
const currentValue = this.state.options?.operation + ',' + this.props.options?.path ?? null;
return (
<div>
{loadingSpec && (
<div className="p-3">
<div className="spinner-border spinner-border-sm text-azure mx-2" role="status"></div>
{this.props.t('stripe', 'Please wait while we load the OpenAPI specification for Stripe.')}
</div>
)}
{options && !loadingSpec && (
<div>
<div className="d-flex stripe-operation-container g-2">
<div className="col-12 form-label">
<label className="form-label">{this.props.t('globals.operation', 'Operation')}</label>
</div>
<div className="col stripe-operation-options flex-grow-1" style={{ width: '90px', marginTop: 0 }}>
<Select
options={this.computeOperationSelectionOptions(specJson)}
value={currentValue}
onChange={(value) => this.changeOperation(value)}
width={'100%'}
useMenuPortal={true}
customOption={this.renderOperationOption}
styles={queryManagerSelectComponentStyle(this.props.darkMode, '100%')}
useCustomStyles={true}
/>
{selectedOperation && (
<small
style={{ margintTop: '10px' }}
className="my-2"
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(selectedOperation.description) }}
/>
)}
</div>
</div>
{selectedOperation && (
<div className={`row stripe-fields-row ${this.props.darkMode && 'theme-dark'}`}>
{pathParams.length > 0 && (
<div className={`path-fields ${Object.keys(requestBody.schema.properties).length === 0 && 'd-none'}`}>
<h5 className="text-heading">{this.props.t('globals.path', 'PATH')}</h5>
<div className="input-group-parent-container">
{pathParams.map((param) => (
<div className="input-group-wrapper" key={param.name}>
<div className="input-group">
<div className="col-auto field field-width-179">
<input
type="text"
value={param.name}
className="form-control border-0"
placeholder="key"
/>
</div>
<div className="col field overflow-hidden">
<CodeHinter
type="basic"
initialValue={this.state.options.params.path[param.name]}
placeholder={'Value'}
onChange={(value) => this.changeParam('path', param.name, value)}
/>
</div>
<span
className="col-auto field-width-28 d-flex"
role="button"
onClick={() => this.removeParam('path', param.name)}
>
<svg
width="100%"
height="100%"
viewBox="0 0 12 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.99931 6.97508L11.0242 12.0014L12 11.027L6.9737 6.00069L12 0.975767L11.0256 0L5.99931 5.0263L0.974388 0L0 0.975767L5.02492 6.00069L0 11.0256L0.974388 12.0014L5.99931 6.97508Z"
fill="#11181C"
/>
</svg>
</span>
</div>
</div>
))}
</div>
</div>
)}
{queryParams.length > 0 && (
<div
className={`query-fields ${Object.keys(requestBody.schema.properties).length === 0 && 'd-none'}`}
>
<h5 className="text-heading">{this.props.t('globals.query'.toUpperCase(), 'QUERY')}</h5>
<div className="input-group-parent-container">
{queryParams.map((param) => (
<div className="input-group-wrapper" key={param.name}>
<div className="input-group">
<div className="col-auto field field-width-179">
<input
type="text"
value={param.name}
className="form-control"
placeholder="key"
disabled
/>
</div>
<div className="col field overflow-hidden">
<CodeHinter
type="basic"
initialValue={this.state.options.params?.query[param.name] ?? ''}
placeholder={'Value'}
onChange={(value) => this.changeParam('query', param.name, value)}
/>
</div>
<span
className="col-auto field-width-28 d-flex"
role="button"
onClick={() => this.removeParam('query', param.name)}
>
<svg
width="100%"
height="100%"
viewBox="0 0 12 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.99931 6.97508L11.0242 12.0014L12 11.027L6.9737 6.00069L12 0.975767L11.0256 0L5.99931 5.0263L0.974388 0L0 0.975767L5.02492 6.00069L0 11.0256L0.974388 12.0014L5.99931 6.97508Z"
fill="#11181C"
/>
</svg>
</span>
</div>
</div>
))}
</div>
</div>
)}
{requestBody.schema.properties && (
<div
className={`request-body-fields d-flex ${
Object.keys(requestBody.schema.properties).length === 0 && 'd-none'
} `}
>
<h5 className="text-heading form-label">{this.props.t('globals.requestBody', 'REQUEST BODY')}</h5>
<div
className={`flex-grow-1 ${
Object.keys(requestBody.schema.properties).length >= 1 && 'input-group-parent-container'
}`}
>
{Object.keys(requestBody.schema.properties).map((param) => (
<div className="input-group-wrapper" key={param.name}>
<div className="input-group">
<div className="col-auto field field-width-179">
<input type="text" value={param} className="form-control" placeholder="key" disabled />
</div>
<div className="col field overflow-hidden">
<CodeHinter
type="basic"
initialValue={this.state.options.params?.request[param] ?? ''}
placeholder={'Value'}
onChange={(value) => this.changeParam('request', param, value)}
/>
</div>
<span
className="col-auto field-width-28 d-flex"
role="button"
onClick={() => this.removeParam('request', param)}
>
<svg
width="100%"
height="100%"
viewBox="0 0 12 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.99931 6.97508L11.0242 12.0014L12 11.027L6.9737 6.00069L12 0.975767L11.0256 0L5.99931 5.0263L0.974388 0L0 0.975767L5.02492 6.00069L0 11.0256L0.974388 12.0014L5.99931 6.97508Z"
fill="#11181C"
/>
</svg>
</span>
</div>
</div>
))}
</div>
</div>
)}
</div>
)}
</div>
)}
</div>
);
}
}
export const Stripe = withTranslation()(StripeComponent);

View file

@ -6,7 +6,6 @@ import { Restapi } from './Restapi';
// eslint-disable-next-line import/no-unresolved
import { Runjs } from './Runjs';
import { Runpy } from './Runpy';
import { Stripe } from './Stripe';
import { Openapi } from './Openapi';
import { Workflows } from './Workflows';
import Grpc from './GRPC';
@ -37,7 +36,6 @@ export const allSources = {
Restapi,
Runjs,
Runpy,
Stripe,
Openapi,
Grpc,
Workflows,

View file

@ -65,7 +65,7 @@ export const Container = ({
return (
<div
className={`jet-container tw-flex tw-flex-col ${properties.loadingState && 'jet-container-loading'} ${
className={`jet-container tw-flex tw-flex-col ${isLoading ? 'jet-container-loading' : ''} ${
properties.showHeader && 'jet-container--with-header'
}`}
id={id}

View file

@ -29,7 +29,7 @@ import { withRouter } from '@/_hoc/withRouter';
import { DATA_SOURCE_TYPE } from '@/_helpers/constants';
import './dataSourceManager.theme.scss';
import { useAppVersionStore } from '@/_stores/appVersionStore';
import { canUpdateDataSource } from '@/_helpers';
class DataSourceManagerComponent extends React.Component {
constructor(props) {
super(props);
@ -807,67 +807,86 @@ class DataSourceManagerComponent extends React.Component {
{...this.props.modalProps}
>
<Modal.Header className={'d-block'}>
<div className="d-flex">
{selectedDataSource && this.props.showBackButton && (
<div
className={`back-btn me-3 mt-3 ${this.props.darkMode ? 'dark' : ''}`}
role="button"
onClick={() => this.setState({ selectedDataSource: false }, () => this.onExit())}
>
<img
data-cy="button-back-ds-connection-modal"
className="m-0"
src="assets/images/icons/back.svg"
width="30"
height="30"
/>
</div>
)}
<Modal.Title className="mt-3">
{selectedDataSource && !isSampleDb ? (
<div className="row selected-ds">
{getSvgIcon(dataSourceMeta?.kind?.toLowerCase(), 35, 35, selectedDataSourceIcon)}
<div className="input-icon" style={{ width: '160px' }}>
<input
type="text"
onChange={(e) => this.onNameChanged(e.target.value)}
className="form-control-plaintext form-control-plaintext-sm color-slate12"
value={decodeEntities(selectedDataSource.name)}
style={{ width: '160px' }}
data-cy="data-source-name-input-filed"
autoFocus
autoComplete="off"
/>
{!this.props.isEditing && (
<span className="input-icon-addon">
<img src="assets/images/icons/edit-source.svg" width="12" height="12" />
</span>
)}
</div>
</div>
) : (
<div className="row">
<div className="col-md-2">
<SolidIcon name="tooljet" />
</div>
<div className="col-md-10"> Sample data source</div>
<div className="d-flex align-items-center justify-content-between">
<div className="d-flex">
{selectedDataSource && this.props.showBackButton && (
<div
className={`back-btn me-3 mt-3 ${this.props.darkMode ? 'dark' : ''}`}
role="button"
onClick={() => this.setState({ selectedDataSource: false }, () => this.onExit())}
>
<img
data-cy="button-back-ds-connection-modal"
className="m-0"
src="assets/images/icons/back.svg"
width="30"
height="30"
/>
</div>
)}
{!selectedDataSource && (
<span className="" data-cy="title-add-new-datasource">
{this.props.t('editor.queryManager.dataSourceManager.addNewDataSource', 'Add new datasource')}
<Modal.Title className="mt-3">
{selectedDataSource && !isSampleDb ? (
<div className="row selected-ds">
{getSvgIcon(dataSourceMeta?.kind?.toLowerCase(), 35, 35, selectedDataSourceIcon)}
<div className="input-icon" style={{ width: '160px' }}>
<input
type="text"
onChange={(e) => this.onNameChanged(e.target.value)}
className="form-control-plaintext form-control-plaintext-sm color-slate12"
value={decodeEntities(selectedDataSource.name)}
style={{ width: '160px' }}
data-cy="data-source-name-input-filed"
autoFocus
autoComplete="off"
disabled={!canUpdateDataSource(selectedDataSource.id)}
/>
{!this.props.isEditing && (
<span className="input-icon-addon">
<img src="assets/images/icons/edit-source.svg" width="12" height="12" />
</span>
)}
</div>
</div>
) : (
<div className="row">
<div className="col-md-2">
<SolidIcon name="tooljet" />
</div>
<div className="col-md-10" data-cy="sample-data-source-title">
{' '}
Sample data source
</div>
</div>
)}
{!selectedDataSource && (
<span className="" data-cy="title-add-new-datasource">
{this.props.t('editor.queryManager.dataSourceManager.addNewDataSource', 'Add new datasource')}
</span>
)}
</Modal.Title>
{!this.props.isEditing && (
<span
data-cy="button-close-ds-connection-modal"
className={`close-btn mx-4 mt-3 ${this.props.darkMode ? 'dark' : ''}`}
onClick={() => this.hideModal()}
>
<SolidIcon name="remove" width="20" fill={'var(--slate12)'} />
</span>
)}
</Modal.Title>
{!this.props.isEditing && (
<span
data-cy="button-close-ds-connection-modal"
className={`close-btn mx-4 mt-3 ${this.props.darkMode ? 'dark' : ''}`}
onClick={() => this.hideModal()}
>
<SolidIcon name="remove" width="20" fill={'var(--slate12)'} />
</span>
)}
</div>
<div className="tw-pt-[15px]">
{this.props.tags &&
this.props.tags.map((tag) => {
if (tag === 'AI') {
return (
<div key={tag} className="tag-container">
<SolidIcon name="AI-tag" />
<span>{tag}</span>
</div>
);
}
})}
</div>
</div>
{this.renderEnvironmentsTab(selectedDataSource)}
</Modal.Header>

View file

@ -12,7 +12,12 @@ import { ChangeDataSource } from './ChangeDataSource';
import { CustomToggleSwitch } from './CustomToggleSwitch';
import { EventManager } from '@/Editor/Inspector/EventManager';
import { staticDataSources, customToggles, mockDataQueryAsComponent, RestAPIToggles } from '../constants';
import { DataSourceTypes } from '../../DataSourceManager/SourceComponents';
import {
DataSourceTypes,
DataBaseSources,
ApiSources,
CloudStorageSources,
} from '../../DataSourceManager/SourceComponents';
import { useDataSources, useGlobalDataSources, useSampleDataSource } from '@/_stores/dataSourcesStore';
import { useDataQueriesActions } from '@/_stores/dataQueriesStore';
import { useSelectedQuery, useSelectedDataSource } from '@/_stores/queryPanelStore';
@ -21,6 +26,7 @@ import { shallow } from 'zustand/shallow';
import SuccessNotificationInputs from './SuccessNotificationInputs';
import ParameterList from './ParameterList';
import { deepClone } from '@/_helpers/utilities/utils.helpers';
import { DATA_SOURCE_TYPE } from '@/_helpers/constants';
export const QueryManagerBody = ({
darkMode,
@ -49,6 +55,10 @@ export const QueryManagerBody = ({
- Ref PR #6763
*/
const [selectedQueryId, setSelectedQueryId] = useState(selectedQuery?.id);
const [dataSourcesKinds, setDataSourcesKinds] = useState([]);
const [userDefinedSources, setUserDefinedSources] = useState(
[...dataSources, ...globalDataSources, !!sampleDataSource && sampleDataSource].filter(Boolean)
);
const queryName = selectedQuery?.name ?? '';
const sourcecomponentName = selectedDataSource?.kind?.charAt(0).toUpperCase() + selectedDataSource?.kind?.slice(1);
@ -64,6 +74,24 @@ export const QueryManagerBody = ({
shallow
);
useEffect(() => {
const shouldAddSampleDataSource = !!sampleDataSource;
const allDataSources = [...dataSources, ...globalDataSources, shouldAddSampleDataSource && sampleDataSource].filter(
Boolean
);
setUserDefinedSources(allDataSources);
const dataSourceKindsList = [...DataBaseSources, ...ApiSources, ...CloudStorageSources];
allDataSources.forEach(({ plugin }) => {
//plugin names are fetched from list data source api call only
if (isEmpty(plugin)) {
return;
}
dataSourceKindsList.push({ name: plugin.name, kind: plugin.pluginId });
});
setDataSourcesKinds(dataSourceKindsList);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataSources]);
useEffect(() => {
setDataSourceMeta(
selectedQuery?.pluginId
@ -308,6 +336,14 @@ export const QueryManagerBody = ({
if (isEmpty(selectableDataSources)) {
return '';
}
const isSampleDb = selectedDataSource?.type === DATA_SOURCE_TYPE.SAMPLE;
const docLink = isSampleDb
? 'https://docs.tooljet.com/docs/data-sources/sample-data-sources'
: selectedDataSource?.pluginId && selectedDataSource.pluginId.trim() !== ''
? `https://docs.tooljet.com/docs/marketplace/plugins/marketplace-plugin-${selectedDataSource?.kind}/`
: `https://docs.tooljet.com/docs/data-sources/${selectedDataSource?.kind}`;
const selectedDataSourceName =
dataSourcesKinds.find((dsk) => dsk.kind === selectedDataSource.kind)?.name || selectedDataSource.kind;
return (
<>
<div className="" ref={paramListContainerRef}>
@ -329,10 +365,11 @@ export const QueryManagerBody = ({
>
<div
className={`d-flex query-manager-border-color hr-text-left py-2 form-label font-weight-500 change-data-source`}
style={{ minWidth: '140px' }}
>
Source
</div>
<div className="d-flex align-items-end" style={{ width: '364px' }}>
<div className="d-flex flex-column align-items-start" style={{ width: '100%' }}>
<ChangeDataSource
dataSources={selectableDataSources}
value={selectedDataSource}
@ -340,6 +377,18 @@ export const QueryManagerBody = ({
changeDataQuery(newDataSource);
}}
/>
<div>
{`To know more about querying ${selectedDataSourceName} data,`}
&nbsp;
<a
href={docLink}
target="_blank"
style={{ marginLeft: '0px !important', color: 'hsl(226, 70.0%, 55.5%)', textDecoration: 'underline' }}
rel="noreferrer"
>
{t('globals.readDocumentation', 'read documentation').toLowerCase()}
</a>
</div>
</div>
</div>
</>

View file

@ -3,12 +3,13 @@ import TabContent from './TabContent';
export default ({
options = [],
jsonBody,
jsonBody, // FIXME: Remove this once data migration to raw_body is complete
rawBody,
theme,
removeKeyValuePair,
addNewKeyValuePair,
onChange,
onJsonBodyChange,
onRawBodyChange,
componentName,
bodyToggle,
}) => {
@ -19,10 +20,11 @@ export default ({
theme={theme}
removeKeyValuePair={removeKeyValuePair}
onChange={onChange}
onJsonBodyChange={onJsonBodyChange}
onRawBodyChange={onRawBodyChange}
componentName={componentName}
tabType={'body'}
jsonBody={jsonBody}
jsonBody={jsonBody} // FIXME: Remove this once data migration to raw_body is complete
rawBody={rawBody}
paramType={'body'}
bodyToggle={bodyToggle}
addNewKeyValuePair={addNewKeyValuePair}

View file

@ -10,8 +10,9 @@ export default ({
options = [],
theme,
onChange,
jsonBody,
onJsonBodyChange,
jsonBody, // FIXME: Remove this once data migration to raw_body is complete
rawBody,
onRawBodyChange,
componentName,
removeKeyValuePair,
paramType,
@ -74,11 +75,10 @@ export default ({
<div>
<CodeHinter
type="extendedSingleLine"
initialValue={jsonBody ?? ''}
lang="javascript"
initialValue={(rawBody || jsonBody) ?? ''} // If raw_body is not set, set initial value to legacy json_body if present
height={'300px'}
className="query-hinter"
onChange={(value) => onJsonBodyChange(value)}
onChange={(value) => onRawBodyChange(value)}
componentName={`${componentName}/${tabType}`}
/>
</div>

View file

@ -10,7 +10,7 @@ function ControlledTabs({
options,
theme,
onChange,
onJsonBodyChange,
onRawBodyChange,
removeKeyValuePair,
addNewKeyValuePair,
darkMode,
@ -34,7 +34,7 @@ function ControlledTabs({
</ListGroup>
{key === 'body' && (
<div className="text-nowrap d-flex align-items-center">
Raw JSON&nbsp;&nbsp;
Raw &nbsp;&nbsp;
<CustomToggleSwitch
toggleSwitchFunction={setBodyToggle}
action="bodyToggle"
@ -78,9 +78,10 @@ function ControlledTabs({
removeKeyValuePair={removeKeyValuePair}
addNewKeyValuePair={addNewKeyValuePair}
onChange={onChange}
onJsonBodyChange={onJsonBodyChange}
onRawBodyChange={onRawBodyChange}
options={options['body']}
jsonBody={options['json_body']}
jsonBody={options['json_body']} // FIXME: Remove this once data migration to raw_body is complete
rawBody={options['raw_body']}
theme={theme}
bodyToggle={bodyToggle}
darkMode={darkMode}

View file

@ -14,7 +14,15 @@ class Restapi extends React.Component {
super(props);
const options = defaults(
{ ...props.options },
{ headers: [['', '']], url_params: [], body: [], json_body: null, body_toggle: false, cookies: [['', '']] }
{
headers: [['', '']],
url_params: [],
body: [],
json_body: null, // FIXME: Remove this once data migration to raw_body is complete
raw_body: null,
body_toggle: false,
cookies: [['', '']],
}
);
this.state = {
options,
@ -105,9 +113,16 @@ class Restapi extends React.Component {
});
};
handleJsonBodyChanged = (jsonBody) => {
handleRawBodyChanged = (rawBody) => {
const { options } = this.state;
options['json_body'] = jsonBody;
// If this is the first time raw_body is set, nullify json_body for data migration
// FIXME: Remove this if condition once data migration to raw_body is complete
if (!options['raw_body'] && options['json_body']) {
options['json_body'] = null;
}
options['raw_body'] = rawBody;
this.setState({ options }, () => {
this.props.optionsChanged(options);
@ -163,12 +178,12 @@ class Restapi extends React.Component {
const currentValue = { label: options.method?.toUpperCase(), value: options.method };
return (
<div className={`d-flex flex-column`}>
{this.props.selectedDataSource?.scope == 'global' && <div className="form-label flex-shrink-0"></div>}{' '}
<div className="flex-grow-1 overflow-hidden">
<div className={`${this.props?.queryName !== 'workflowNode' && 'd-flex'}`}>
{this.props?.queryName !== 'workflowNode' && <div className="form-label flex-shrink-0">Request</div>}
<div className="flex-grow-1">
<div className="rest-api-methods-select-element-container">
<div className={`me-2`} style={{ width: '90px', height: '32px' }}>
<label className="font-weight-medium color-slate12">Method</label>
<label className="font-weight-bold color-slate12">Method</label>
<Select
options={[
{ label: 'GET', value: 'get' },
@ -191,12 +206,15 @@ class Restapi extends React.Component {
</div>
<div className={`field w-100 rest-methods-url`}>
<div className="font-weight-medium color-slate12">URL</div>
<div className="font-weight-bold color-slate12">URL</div>
<div className="d-flex">
{dataSourceURL && (
<BaseUrl theme={this.props.darkMode ? 'monokai' : 'default'} dataSourceURL={dataSourceURL} />
)}
<div className={`flex-grow-1 ${dataSourceURL ? 'url-input-group' : ''}`}>
<div
className={`flex-grow-1 rest-api-url-codehinter ${dataSourceURL ? 'url-input-group' : ''}`}
style={{ width: '530px' }}
>
<CodeHinter
type="basic"
initialValue={options.url}
@ -211,20 +229,20 @@ class Restapi extends React.Component {
</div>
</div>
</div>
</div>
<div className={`query-pane-restapi-tabs`}>
<Tabs
theme={this.props.darkMode ? 'monokai' : 'default'}
options={this.state.options}
onChange={this.handleChange}
onJsonBodyChange={this.handleJsonBodyChanged}
removeKeyValuePair={this.removeKeyValuePair}
addNewKeyValuePair={this.addNewKeyValuePair}
darkMode={this.props.darkMode}
componentName={queryName}
bodyToggle={this.state.options.body_toggle}
setBodyToggle={this.onBodyToggleChanged}
/>
<div className={`query-pane-restapi-tabs`}>
<Tabs
theme={this.props.darkMode ? 'monokai' : 'default'}
options={this.state.options}
onChange={this.handleChange}
onRawBodyChange={this.handleRawBodyChanged}
removeKeyValuePair={this.removeKeyValuePair}
addNewKeyValuePair={this.addNewKeyValuePair}
darkMode={this.props.darkMode}
componentName={queryName}
bodyToggle={this.state.options.body_toggle}
setBodyToggle={this.onBodyToggleChanged}
/>
</div>
</div>
</div>
);

View file

@ -1,381 +0,0 @@
import React from 'react';
// import 'codemirror/theme/duotone-light.css';
import DOMPurify from 'dompurify';
import Select from '@/_ui/Select';
import { openapiService } from '@/_services';
import { withTranslation } from 'react-i18next';
import { queryManagerSelectComponentStyle } from '@/_ui/Select/styles';
import CodeHinter from '@/Editor/CodeEditor';
const operationColorMapping = {
get: 'azure',
post: 'green',
delete: 'red',
put: 'yellow',
};
class StripeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
loadingSpec: true,
};
}
componentDidMount() {
const queryParams = {
path: this.props.options?.params?.path ?? {},
query: this.props.options?.params?.query ?? {},
request: this.props.options?.params?.request ?? {},
};
this.setState({
loadingSpec: true,
options: {
...this.props.options,
params: queryParams,
},
});
this.fetchOpenApiSpec();
}
fetchOpenApiSpec = () => {
this.setState({ loadingSpec: true });
openapiService
.fetchSpecFromUrl('https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json')
.then((response) => {
response.text().then((text) => {
const data = JSON.parse(text);
this.setState({ specJson: data, loadingSpec: false });
});
});
};
changeOption(option, value) {
this.setState({
options: {
...this.state.options,
[option]: value,
},
});
}
changeOperation = (value) => {
const operation = value.split(',')[0];
const path = value.split(',')[1];
this.setState(
{
options: {
...this.state.options,
path,
operation,
selectedOperation: this.state.specJson.paths[path][operation],
},
},
() => {
this.props.optionsChanged(this.state.options);
}
);
};
changeParam = (paramType, paramName, value) => {
const options = this.state.options;
const newOptions = {
...options,
params: {
...options.params,
[paramType]: {
...options.params[paramType],
[paramName]: value,
},
},
};
this.setState({
options: newOptions,
});
this.props.optionsChanged(newOptions);
};
removeParam = (paramType, paramName) => {
const newOptions = JSON.parse(JSON.stringify(this.state.options));
newOptions['params'][paramType][paramName] = undefined;
this.setState(
{
options: newOptions,
},
() => {
this.props.optionsChanged(newOptions);
}
);
};
renderOperationOption = (props) => {
const path = props.value;
const operation = props.label;
if (path && operation) {
return (
<div className="row">
<div className="col-auto" style={{ width: '60px' }}>
<span className={`badge bg-${operationColorMapping[operation]}`}>{operation}</span>
</div>
<div className="col">
<span>{path}</span>
</div>
</div>
);
} else {
return 'Select an operation';
}
};
computeOperationSelectionOptions = (operationOptions) => {
let options = [];
const paths = operationOptions?.paths;
if (paths) {
for (const path of Object.keys(paths)) {
for (const operation of Object.keys(paths[path])) {
options.push({
value: `${operation},${path}`,
name: path,
operation: operation,
});
}
}
}
return options;
};
render() {
const { options, specJson, loadingSpec } = this.state;
const selectedOperation = options?.selectedOperation;
let pathParams = [];
let queryParams = [];
let requestBody = [];
if (selectedOperation) {
if (selectedOperation.parameters) {
pathParams = selectedOperation.parameters.filter((param) => param.in === 'path');
queryParams = selectedOperation.parameters.filter((param) => param.in === 'query');
}
if (selectedOperation.requestBody) {
const requestType = Object.keys(selectedOperation.requestBody.content)[0];
requestBody = selectedOperation.requestBody.content[requestType];
}
}
const currentValue = this.state.options?.operation + ',' + this.props.options?.path ?? null;
return (
<div>
{loadingSpec && (
<div className="p-3">
<div className="spinner-border spinner-border-sm text-azure mx-2" role="status"></div>
{this.props.t('stripe', 'Please wait while we load the OpenAPI specification for Stripe.')}
</div>
)}
{options && !loadingSpec && (
<div>
<div className="d-flex g-2">
<div className="col-12 form-label">
<label className="form-label">{this.props.t('globals.operation', 'Operation')}</label>
</div>
<div className="col stripe-operation-options flex-grow-1" style={{ width: '90px', marginTop: 0 }}>
<Select
options={this.computeOperationSelectionOptions(specJson)}
value={currentValue}
onChange={(value) => this.changeOperation(value)}
width={'100%'}
useMenuPortal={true}
customOption={this.renderOperationOption}
styles={queryManagerSelectComponentStyle(this.props.darkMode, '100%')}
useCustomStyles={true}
/>
{selectedOperation && (
<small
style={{ margintTop: '10px' }}
className="my-2"
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(selectedOperation.description) }}
/>
)}
</div>
</div>
{selectedOperation && (
<div className={`row stripe-fields-row ${this.props.darkMode && 'theme-dark'}`}>
{pathParams.length > 0 && (
<div className={`path-fields ${Object.keys(requestBody.schema.properties).length === 0 && 'd-none'}`}>
<h5 className="text-heading">{this.props.t('globals.path', 'PATH')}</h5>
<div className="input-group-parent-container">
{pathParams.map((param) => (
<div className="input-group-wrapper" key={param.name}>
<div className="input-group">
<div className="col-auto field field-width-179">
<input
type="text"
value={param.name}
className="form-control border-0"
placeholder="key"
/>
</div>
<div className="col field overflow-hidden">
<CodeHinter
type="basic"
initialValue={this.state.options.params.path[param.name]}
placeholder={'Value'}
onChange={(value) => this.changeParam('path', param.name, value)}
/>
</div>
<span
className="col-auto field-width-28 d-flex"
role="button"
onClick={() => this.removeParam('path', param.name)}
>
<svg
width="100%"
height="100%"
viewBox="0 0 12 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.99931 6.97508L11.0242 12.0014L12 11.027L6.9737 6.00069L12 0.975767L11.0256 0L5.99931 5.0263L0.974388 0L0 0.975767L5.02492 6.00069L0 11.0256L0.974388 12.0014L5.99931 6.97508Z"
fill="#11181C"
/>
</svg>
</span>
</div>
</div>
))}
</div>
</div>
)}
{queryParams.length > 0 && (
<div
className={`query-fields ${Object.keys(requestBody.schema.properties).length === 0 && 'd-none'}`}
>
<h5 className="text-heading">{this.props.t('globals.query'.toUpperCase(), 'QUERY')}</h5>
<div className="input-group-parent-container">
{queryParams.map((param) => (
<div className="input-group-wrapper" key={param.name}>
<div className="input-group">
<div className="col-auto field field-width-179">
<input
type="text"
value={param.name}
className="form-control"
placeholder="key"
disabled
/>
</div>
<div className="col field overflow-hidden">
<CodeHinter
type="basic"
initialValue={this.state.options.params?.query[param.name] ?? ''}
placeholder={'Value'}
onChange={(value) => this.changeParam('query', param.name, value)}
/>
</div>
<span
className="col-auto field-width-28 d-flex"
role="button"
onClick={() => this.removeParam('query', param.name)}
>
<svg
width="100%"
height="100%"
viewBox="0 0 12 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.99931 6.97508L11.0242 12.0014L12 11.027L6.9737 6.00069L12 0.975767L11.0256 0L5.99931 5.0263L0.974388 0L0 0.975767L5.02492 6.00069L0 11.0256L0.974388 12.0014L5.99931 6.97508Z"
fill="#11181C"
/>
</svg>
</span>
</div>
</div>
))}
</div>
</div>
)}
{requestBody.schema.properties && (
<div
className={`request-body-fields d-flex ${
Object.keys(requestBody.schema.properties).length === 0 && 'd-none'
} `}
>
<h5 className="text-heading form-label">{this.props.t('globals.requestBody', 'REQUEST BODY')}</h5>
<div
className={`flex-grow-1 ${
Object.keys(requestBody.schema.properties).length >= 1 && 'input-group-parent-container'
}`}
>
{Object.keys(requestBody.schema.properties).map((param) => (
<div className="input-group-wrapper" key={param.name}>
<div className="input-group">
<div className="col-auto field field-width-179">
<input type="text" value={param} className="form-control" placeholder="key" disabled />
</div>
<div className="col field overflow-hidden">
<CodeHinter
type="basic"
initialValue={this.state.options.params?.request[param] ?? ''}
placeholder={'Value'}
onChange={(value) => this.changeParam('request', param, value)}
/>
</div>
<span
className="col-auto field-width-28 d-flex"
role="button"
onClick={() => this.removeParam('request', param)}
>
<svg
width="100%"
height="100%"
viewBox="0 0 12 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.99931 6.97508L11.0242 12.0014L12 11.027L6.9737 6.00069L12 0.975767L11.0256 0L5.99931 5.0263L0.974388 0L0 0.975767L5.02492 6.00069L0 11.0256L0.974388 12.0014L5.99931 6.97508Z"
fill="#11181C"
/>
</svg>
</span>
</div>
</div>
))}
</div>
</div>
)}
</div>
)}
</div>
)}
</div>
);
}
}
export const Stripe = withTranslation()(StripeComponent);

View file

@ -6,7 +6,6 @@ import { Restapi } from './Restapi';
// eslint-disable-next-line import/no-unresolved
import { Runjs } from './Runjs';
import { Runpy } from './Runpy';
import { Stripe } from './Stripe';
import { Openapi } from './Openapi';
import Grpc from './GRPC';
import tooljetDbOperations from './TooljetDatabase/operations.json';
@ -36,7 +35,6 @@ export const allSources = {
Restapi,
Runjs,
Runpy,
Stripe,
Openapi,
Grpc,
};

View file

@ -289,6 +289,7 @@ export const tableConfig = {
onCellValueChanged: { displayName: 'Cell value changed' },
onFilterChanged: { displayName: 'Filter changed' },
onNewRowsAdded: { displayName: 'Add new rows' },
onTableDataDownload: { displayName: 'Download data' },
},
styles: {
textColor: {

View file

@ -13,19 +13,21 @@ import {
CloudStorageSources,
CommonlyUsedDataSources,
} from '@/Editor/DataSourceManager/SourceComponents';
import { pluginsService, globalDatasourceService, authenticationService } from '@/_services';
import { pluginsService, globalDatasourceService, authenticationService, marketplaceService } from '@/_services';
import { Card } from '@/_ui/Card';
import { SegregatedList } from '../SegregatedList';
import { SearchBox } from '@/_components';
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import { BreadCrumbContext } from '@/App';
import { canDeleteDataSource } from '@/_helpers';
import { fetchAndSetWindowTitle, pageTitles } from '@white-label/whiteLabelling';
import HeaderSkeleton from '../../_ui/FolderSkeleton/HeaderSkeleton';
import Skeleton from 'react-loading-skeleton';
export const GlobalDataSourcesPage = ({ darkMode = false, updateSelectedDatasource }) => {
const containerRef = useRef(null);
const [plugins, setPlugins] = useState([]);
const [marketplacePlugins, setMarketplacePlugins] = useState([]);
const [filteredDataSources, setFilteredDataSources] = useState([]);
const [queryString, setQueryString] = useState('');
const [addingDataSource, setAddingDataSource] = useState(false);
@ -54,7 +56,10 @@ export const GlobalDataSourcesPage = ({ darkMode = false, updateSelectedDatasour
setCurrentEnvironment,
activeDatasourceList,
setActiveDatasourceList,
canCreateDataSource,
canUpdateDataSource,
isLoading,
environmentLoading,
} = useContext(GlobalDataSourcesContext);
const { updateSidebarNAV } = useContext(BreadCrumbContext);
@ -66,6 +71,13 @@ export const GlobalDataSourcesPage = ({ darkMode = false, updateSelectedDatasour
.catch((error) => {
toast.error(error?.message || 'Failed to fetch plugins');
});
marketplaceService
.findAll()
.then(({ data = [] }) => setMarketplacePlugins([...data]))
.catch((error) => {
toast.error(error?.message || 'Failed to fetch plugins');
});
}, []);
useEffect(() => {
@ -320,23 +332,38 @@ export const GlobalDataSourcesPage = ({ darkMode = false, updateSelectedDatasour
};
});
const pluginsWithTags = marketplacePlugins.reduce((acc, plugin) => {
const isInDatasources = datasources.some((datasource) => {
return datasource.kind === plugin.id || datasource.pluginId === plugin.id || datasource.plugin_id === plugin.id;
});
if (isInDatasources && plugin.tags) {
acc[plugin.id] = plugin.tags;
}
return acc;
}, {});
return (
<>
<div className="row row-deck mt-3">
{datasources.map((item) => (
<Card
key={item.key}
darkMode={darkMode}
title={item.title}
src={item?.src}
usePluginIcon={isEmpty(item?.iconFile?.data)}
height={'35px'}
width={'35px'}
actionButton={addDataSourceBtn(item)}
className="datasource-card"
titleClassName={'datasource-card-title'}
/>
))}
{datasources.map((item) => {
const tags =
pluginsWithTags[item.kind] || pluginsWithTags[item.pluginId] || pluginsWithTags[item.plugin_id] || [];
return (
<Card
key={item.key}
darkMode={darkMode}
title={item.title}
src={item?.src}
usePluginIcon={isEmpty(item?.iconFile?.data)}
height={'35px'}
width={'35px'}
actionButton={addDataSourceBtn(item)}
className="datasource-card"
titleClassName={'datasource-card-title'}
tags={tags}
/>
);
})}
{type === 'Plugins' && (
<div style={{ height: '122px', width: '164px' }} className={`col-md-2 mb-4 `}>
<div
@ -352,7 +379,7 @@ export const GlobalDataSourcesPage = ({ darkMode = false, updateSelectedDatasour
data-cy={`data-source-add-plugin`}
>
<div className="card-body">
<center style={{ paddingTop: '5px' }}>
<center style={{ paddingTop: '5px', marginTop: '20px' }}>
<SolidIcon
name="plus"
fill={'var(--icon-default)'}
@ -418,6 +445,15 @@ export const GlobalDataSourcesPage = ({ darkMode = false, updateSelectedDatasour
return dataSourceList;
};
const selectedPlugin = marketplacePlugins.find(
(plugin) =>
plugin.id === selectedDataSource?.kind ||
plugin.id === selectedDataSource?.pluginId ||
plugin.id === selectedDataSource?.plugin_id
);
const tags = selectedPlugin?.tags || [];
return (
<div className="row gx-0">
<Sidebar renderSidebarList={renderSidebarList} updateSelectedDatasource={updateSelectedDatasource} />
@ -438,6 +474,9 @@ export const GlobalDataSourcesPage = ({ darkMode = false, updateSelectedDatasour
container={selectedDataSource ? containerRef?.current : null}
isEditing={isEditing}
updateSelectedDatasource={updateSelectedDatasource}
showSaveBtn={canCreateDataSource() || canUpdateDataSource(selectedDataSource?.id) || canDeleteDataSource()}
environmentLoading={environmentLoading}
tags={tags}
/>
)}
{isLoading && loadingState()}

View file

@ -193,17 +193,19 @@ const ConstantForm = ({
{error['name']}
</span>
{!error['name'] && (
<small style={{ color: 'var(--text-placeholder)' }}>Name must be unique and max 50 characters</small>
<small style={{ color: 'var(--text-placeholder)' }} data-cy="name-info">
Name must be unique and max 50 characters
</small>
)}
</div>
</div>
<div className="form-group">
<label className="form-label" data-cy="name-label">
<label className="form-label" data-cy="type-label">
Type
</label>
<div className="radio-group" data-tooltip-id="type-tooltip">
<div className="radio-item">
<label style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }}>
<label style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }} data-cy="global-constants-label">
<input
type="radio"
name="type"
@ -211,15 +213,16 @@ const ConstantForm = ({
checked={fields['type'] === Constants.Global}
onChange={handleFieldChange}
disabled={mode === 'edit'}
data-cy="global-constants-input"
/>
Global constants
</label>
<small style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }}>
<small style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }} data-cy="global-constants-info">
The values can be used anywhere in the product
</small>
</div>
<div className="radio-item">
<label style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }}>
<label style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }} data-cy="secrets-constants-label">
<input
type="radio"
name="type"
@ -227,10 +230,11 @@ const ConstantForm = ({
checked={fields['type'] === Constants.Secret}
onChange={handleFieldChange}
disabled={mode === 'edit'}
data-cy="secrets-constants-input"
/>
Secrets
</label>
<small style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }}>
<small style={{ color: mode === 'edit' ? '#adb5bd' : 'inherit' }} data-cy="secrets-constants-info">
The values are hidden and can only be used in data sources and queries
</small>
</div>
@ -246,7 +250,7 @@ const ConstantForm = ({
<label className="form-label" data-cy="value-label">
Value
</label>
<small className="text-green d-flex align-items-center" data-cy="encrypted-label">
<small className="text-green d-flex align-items-center" data-cy="form-encrypted-label">
<img
className="encrypted-icon me-1"
src="assets/images/icons/padlock.svg"

View file

@ -52,7 +52,7 @@ const ConstantTable = ({
{' '}
<small
className="text-green d-flex align-items-center justify-content-end"
data-cy="encrypted-label"
data-cy="table-encrypted-label"
>
<img
className="encrypted-icon me-1"

View file

@ -19,7 +19,7 @@ const EmptyState = ({ canCreateVariable, setIsManageVarDrawerOpen, isLoading, se
</p>
{canCreateVariable && searchTerm === '' && (
<ButtonSolid
data-cy="add-new-constant-button"
data-cy="table-add-new-constant-button"
vaiant="primary"
onClick={() => setIsManageVarDrawerOpen(true)}
className="add-new-constant-button"

View file

@ -454,7 +454,7 @@ const ManageOrgConstantsComponent = ({ darkMode }) => {
<div className="workspace-setting-buttons-wrap">
{canCreateVariable() && (
<ButtonSolid
data-cy="add-new-constant-button"
data-cy="form-add-new-constant-button"
variant="primary"
onClick={() => {
setMode(() => MODES.CREATE);

View file

@ -237,7 +237,7 @@ function InviteUsersForm({
className="invite-email-body"
id="inviteByEmail"
>
<label className="form-label" data-cy="label-full-name-input-field">
<label className="form-label" data-cy="name-label">
Name
</label>
<div className="form-group mb-3 ">
@ -255,7 +255,7 @@ function InviteUsersForm({
name="fullName"
onChange={changeNewUserOption.bind(this, 'fullName')}
value={fields['fullName']}
data-cy="input-field-full-name"
data-cy="name-input"
disabled={isEditing}
/>
<span className="text-danger" data-cy="error-message-fullname">
@ -265,7 +265,7 @@ function InviteUsersForm({
</ToolTip>
</div>
<div className="form-group mb-3 ">
<label className="form-label" data-cy="label-email-input-field">
<label className="form-label" data-cy="email-label">
{t('header.organization.menus.manageUsers.emailAddress', 'Email Address')}
</label>
<ToolTip
@ -283,7 +283,7 @@ function InviteUsersForm({
name="email"
onChange={changeNewUserOption.bind(this, 'email')}
value={fields['email']}
data-cy="input-field-email"
data-cy="email-input"
disabled={isEditing}
/>
<span className="text-danger" data-cy="error-message-email">
@ -293,7 +293,7 @@ function InviteUsersForm({
</ToolTip>
</div>
<div className="form-group mb-3 manage-groups-invite-form" data-cy="user-group-select">
<label className="form-label" data-cy="label-group-input-field">
<label className="form-label" data-cy="user-group-label">
{isEditing
? 'User groups'
: t('header.organization.menus.manageUsers.selectGroup', 'Select Group')}

View file

@ -3,8 +3,9 @@ import cx from 'classnames';
import { pluginsService } from '@/_services';
import { toast } from 'react-hot-toast';
import Spinner from '@/_ui/Spinner';
import { capitalizeFirstLetter } from './utils';
import { capitalizeFirstLetter, useTagsByPluginId } from './utils';
import { ConfirmDialog } from '@/_components';
import Icon from '@/_ui/Icon/SolidIcons';
export const InstalledPlugins = ({
allPlugins = [],
@ -14,7 +15,7 @@ export const InstalledPlugins = ({
ENABLE_MARKETPLACE_DEV_MODE,
}) => {
return (
<div className="col-9 pb-3">
<div className="col-9 pb-3" style={{ marginLeft: 'auto' }}>
{fetching && (
<div className="m-auto text-center">
<Spinner />
@ -53,7 +54,8 @@ const InstalledPluginCard = ({ plugin, marketplacePlugin, fetchPlugins, isDevMod
const [isDeletingPlugin, setDeletingPlugin] = React.useState(false);
const darkMode = localStorage.getItem('darkMode') === 'true';
const { id, name } = plugin;
const { id, name, pluginId } = plugin;
const { tags } = useTagsByPluginId(pluginId);
const executePluginDeletion = () => {
setDeleteModalVisibility(true);
@ -143,7 +145,19 @@ const InstalledPluginCard = ({ plugin, marketplacePlugin, fetchPlugins, isDevMod
</span>
</div>
<div className="col">
<div className="font-weight-medium text-capitalize">{plugin.name}</div>
<div className="d-flex align-items-center tw-gap-[6px]">
<div className="font-weight-medium text-capitalize">{plugin.name}</div>
{tags.map((tag) => {
if (tag === 'AI') {
return (
<div key={tag} className="tag-container">
<Icon name="AI-tag" />
<span>{tag}</span>
</div>
);
}
})}
</div>
<div>{plugin.description}</div>
</div>
<div className="col-2">

View file

@ -3,12 +3,15 @@ import config from 'config';
import cx from 'classnames';
import { toast } from 'react-hot-toast';
import { pluginsService } from '@/_services';
import { capitalizeFirstLetter } from './utils';
import { capitalizeFirstLetter, useTagsByPluginId } from './utils';
import Icon from '@/_ui/Icon/SolidIcons';
export const MarketplaceCard = ({ id, name, repo, description, version, isInstalled = false }) => {
const [installed, setInstalled] = React.useState(isInstalled);
const [installing, setInstalling] = React.useState(false);
const { tags } = useTagsByPluginId(id);
React.useEffect(() => {
setInstalled(isInstalled);
}, [isInstalled]);
@ -53,7 +56,19 @@ export const MarketplaceCard = ({ id, name, repo, description, version, isInstal
</span>
</div>
<div className="col">
<div className="font-weight-medium text-capitalize">{name}</div>
<div className="tw-flex tw-items-center tw-gap-[6px]">
<div className="font-weight-medium text-capitalize">{name}</div>
{tags.map((tag) => {
if (tag === 'AI') {
return (
<div key={tag} className="tag-container">
<Icon name="AI-tag" />
<span>{tag}</span>
</div>
);
}
})}
</div>
<div>{description}</div>
</div>
</div>

View file

@ -26,7 +26,7 @@ export const MarketplacePlugins = ({ allPlugins = [] }) => {
}, []);
return (
<div className="col-9 pb-3">
<div className="col-9 pb-3" style={{ marginLeft: 'auto' }}>
<div className="row row-cards">
{allPlugins?.map(({ id, name, repo, version, description }) => {
return (

View file

@ -1,3 +1,25 @@
import { useEffect, useState } from 'react';
import { marketplaceService } from '@/_services';
import toast from 'react-hot-toast';
export function capitalizeFirstLetter(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
export const useTagsByPluginId = (id) => {
const [tags, setTags] = useState([]);
useEffect(() => {
marketplaceService
.findAll()
.then(({ data = [] }) => {
const plugin = data.find((plugin) => plugin.id === id);
setTags(plugin?.tags || []);
})
.catch((error) => {
toast.error(error?.message || 'Failed to fetch plugins');
});
}, [id]);
return { tags };
};

View file

@ -1,17 +1,36 @@
import React, { useState, useContext } from 'react';
import React, { useState } from 'react';
import cx from 'classnames';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import Popover from 'react-bootstrap/Popover';
import { FilterForm } from '../Forms/FilterForm';
import { isEmpty } from 'lodash';
// import { pluralize } from '@/_helpers/utils';
import { pluralize } from '@/_helpers/utils';
import { useMounted } from '@/_hooks/use-mount';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
import AddRectangle from '@/_ui/Icon/bulkIcons/AddRectangle';
import ClearIndicator from '@/_ui/Icon/bulkIcons/ClearIndicator';
import InfoIcon from '@assets/images/icons/info.svg';
import { deepClone } from '@/_helpers/utilities/utils.helpers';
import './styles.scss';
import { toast } from 'react-hot-toast';
const Filter = ({ filters, setFilters, handleBuildFilterQuery, resetFilterQuery, setFilterEnable, filterEnable }) => {
const Filter = ({
filters,
setFilters,
handleBuildFilterQuery,
resetFilterQuery,
setFilterEnable,
filterEnable,
setActiveFilters,
}) => {
const [tempFilters, setTempFilters] = useState(deepClone(filters));
const [show, setShow] = useState(false);
const darkMode = localStorage.getItem('darkMode') === 'true';
const filterKeys = Object.keys(filters);
const filterKeys = Object.keys(tempFilters);
const tempFilterCount = Object.keys(tempFilters).length;
const filterCount = Object.keys(filters).length;
const validFilterCountRef = React.useRef(0);
const isMounted = useMounted();
const reset = () => {
@ -19,39 +38,133 @@ const Filter = ({ filters, setFilters, handleBuildFilterQuery, resetFilterQuery,
setShow(false);
};
const generateMessage = (operator) => {
const operatorMessage = {
gte: 'Greater than or equal',
lt: 'Less than',
gt: 'Greater than',
eq: 'Equals',
lte: 'Less than or equal',
neq: 'Not equal',
};
return operatorMessage[operator];
};
React.useEffect(() => {
setActiveFilters(filterCount);
}, [filterCount, setActiveFilters]);
const allValidFilters = React.useMemo(() => {
const filteredFilters = Object.values(tempFilters).filter(
({ column, operator, value }) => column || operator || value
);
if (filteredFilters.length === 0 && filterCount === 0) {
validFilterCountRef.current = 0;
return false;
}
if (filteredFilters.length === 0 && filterCount !== 0 && tempFilterCount !== 0) {
validFilterCountRef.current = 0;
return false;
}
validFilterCountRef.current = filteredFilters.length;
return filteredFilters.every(({ column, operator, value }) => column && operator && value);
}, [tempFilters]);
const popover = (
<Popover id="storage-filter-popover" className={cx({ 'dark-theme': darkMode })} data-cy="filter-section">
<Popover.Body bsPrefix="storage-filter-popover">
<div className="card-body" data-cy="filter-card-body">
{Object.values(filters).map((filter, index) => {
return (
<div key={index}>
<FilterForm {...filter} filters={filters} index={filterKeys[index]} setFilters={setFilters} />
</div>
);
})}
</div>
<div
className="card-footer cursor-pointer"
data-cy="filter-card-footer"
onClick={() =>
setFilters((prevFilters) => ({ ...prevFilters, [+Object.keys(prevFilters).pop() + 1 || 0]: {} }))
}
>
<svg
width="11"
height="11"
viewBox="0 0 11 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
data-cy="add-condition-link"
<Popover
id="storage-filter-popover"
className={cx('filter-popup', { 'dark-theme': darkMode })}
data-cy="filter-section"
>
<Popover.Body bsPrefix="storage-filter-popover" style={{ height: '100%' }}>
<div className="filter-header">
<span className="filter-heading">Filters</span>
<span
className="cursor-pointer"
onClick={() => {
setShow(false);
setTempFilters(deepClone(filters));
}}
>
<path
d="M5.34554 10.0207C5.15665 10.0207 4.99832 9.95678 4.87054 9.829C4.74276 9.70123 4.67887 9.54289 4.67887 9.354V5.854H1.17887C0.989985 5.854 0.831651 5.79011 0.703874 5.66234C0.576096 5.53456 0.512207 5.37623 0.512207 5.18734C0.512207 4.99845 0.576096 4.84012 0.703874 4.71234C0.831651 4.58456 0.989985 4.52067 1.17887 4.52067H4.67887V1.02067C4.67887 0.831782 4.74276 0.673448 4.87054 0.54567C4.99832 0.417893 5.15665 0.354004 5.34554 0.354004C5.53443 0.354004 5.69276 0.417893 5.82054 0.54567C5.94832 0.673448 6.01221 0.831782 6.01221 1.02067V4.52067H9.51221C9.7011 4.52067 9.85943 4.58456 9.98721 4.71234C10.115 4.84012 10.1789 4.99845 10.1789 5.18734C10.1789 5.37623 10.115 5.53456 9.98721 5.66234C9.85943 5.79011 9.7011 5.854 9.51221 5.854H6.01221V9.354C6.01221 9.54289 5.94832 9.70123 5.82054 9.829C5.69276 9.95678 5.53443 10.0207 5.34554 10.0207Z"
fill="#466BF2"
/>
</svg>
&nbsp;Add Condition
<SolidIcon name="remove" fill={darkMode ? '#C1C8CD' : '#6A727C'} />
</span>
</div>
<div className="card-body filter-body" data-cy="filter-card-body">
{tempFilterCount === 0 && (
<div className="empty-filters-value">
<InfoIcon style={{ width: '16px', marginRight: '5px' }} />
<span>There are no filters added</span>
</div>
)}
{tempFilterCount > 0 && (
<>
<div className="filter-title">
<span className="width-lg">Column</span>
<span className="width-sm">Operation</span>
<span className="width-lg">Value</span>
</div>
{Object.values(tempFilters).map((filter, index) => {
return (
<div key={index} className="tw-pb-1 filter-content">
<FilterForm
{...filter}
filters={tempFilters}
index={filterKeys[index]}
setFilters={setTempFilters}
generateMessage={generateMessage}
/>
</div>
);
})}
</>
)}
<div className="tw-mt-1 tw-pl-2">
<ButtonSolid
variant="ghostBlue"
size="sm"
onClick={() =>
setTempFilters((prevFilters) => ({ ...prevFilters, [+Object.keys(prevFilters).pop() + 1 || 0]: {} }))
}
>
<AddRectangle width="15" fill="#3E63DD" opacity="1" secondaryFill="#ffffff" />
Add filter
</ButtonSolid>
</div>
</div>
<div className="card-footer filter-footer" data-cy="filter-card-footer">
{filterCount > 0 && tempFilterCount > 0 && (
<ButtonSolid
variant="ghostBlue"
size="sm"
onClick={() => {
setTempFilters({});
}}
>
<ClearIndicator width="15" fill="#3E63DD" opacity="1" secondaryFill="#ffffff" />
Clear all
</ButtonSolid>
)}
<ButtonSolid
variant="tertiary"
size="sm"
onClick={() => {
setTempFilters(deepClone(filters));
document.activeElement.blur();
}}
>
Cancel
</ButtonSolid>
<ButtonSolid
variant="primary"
size="sm"
onClick={() => {
setFilters(tempFilters);
setShow(false);
}}
disabled={!allValidFilters || (filterCount === 0 && tempFilterCount === 0)}
>
Apply
</ButtonSolid>
</div>
</Popover.Body>
</Popover>
@ -69,14 +182,34 @@ const Filter = ({ filters, setFilters, handleBuildFilterQuery, resetFilterQuery,
reset();
resetFilterQuery();
} else {
let validFilters = { ...filters };
let hasInvalidFilter = false;
Object.keys(filters).map((key) => {
if (!isEmpty(filters[key])) {
const { column, operator, value } = filters[key];
if (!isEmpty(column) && !isEmpty(operator) && !isEmpty(value)) {
handleBuildFilterQuery(filters);
if (value.toLowerCase() === 'null' && operator !== 'is') {
delete validFilters[key];
hasInvalidFilter = true;
toast.error(
`Invalid filter operation: Cannot use '${generateMessage(
operator
)}' operator with a NULL value for column '${column}'.`,
{ position: 'top-center' }
);
}
}
}
});
if (hasInvalidFilter) {
setFilters(validFilters);
}
if (Object.keys(validFilters).length > 0) {
handleBuildFilterQuery(validFilters);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(filters)]);
@ -88,25 +221,58 @@ const Filter = ({ filters, setFilters, handleBuildFilterQuery, resetFilterQuery,
trigger="click"
show={show}
onToggle={(show) => {
if (show && isEmpty(filters)) setFilters({ 0: {} });
if (show && isEmpty(filters)) setTempFilters({ 0: {} });
if (show && !isEmpty(filters)) setTempFilters(deepClone(filters));
setShow(show);
}}
placement="bottom-start"
overlay={popover}
>
<button
data-cy="filter-button"
className={cx('tj-db-filter-btn tj-text-xsm font-weight-500 ghost-black-operation', {
'tj-db-filter-btn-applied': areFiltersApplied,
'tj-db-filter-btn-active': show,
})}
>
<SolidIcon name="filter" width="14" fill={areFiltersApplied ? '#46A758' : show ? '#3E63DD' : '#889096'} />
&nbsp;&nbsp;Filter
{/* {areFiltersApplied && (
<span>ed by {pluralize(Object.values(filters).filter(checkIsFilterObjectEmpty).length, 'column')}</span>
)} */}
</button>
<div className={cx('tw-flex', 'tw-relative')}>
<button
data-cy="filter-button"
className={cx('tj-db-filter-btn tj-text-xsm font-weight-500 ghost-black-operation', {
'tj-db-filter-btn-applied': areFiltersApplied,
'tj-db-filter-btn-active-filter': show && filterCount > 0,
'tj-db-filter-btn-active': show && filterCount === 0,
})}
>
<SolidIcon
name="filter"
width="14px"
fill={
areFiltersApplied
? '#3E63DD'
: show && filterCount === 0
? '#ACB2B9'
: show && filterCount > 0
? '#4368E3'
: '#889096'
}
/>
<div className="tw-flex items-center tw-ml-[3px]">
{filterCount > 0 ? (
<span>{pluralize(validFilterCountRef.current, 'filter')}</span>
) : (
<div>&nbsp;&nbsp;Filter</div>
)}
</div>
{/* {areFiltersApplied && (
<span>ed by {pluralize(Object.values(filters).filter(checkIsFilterObjectEmpty).length, 'column')}</span>
)} */}
</button>
{filterCount > 0 && (
<div
className="tw-absolute tw-right-[-20px] tw-z-50 tw-w-7 tw-h-7 tw-flex tw-items-center tw-justify-center tw-p-[7px] cursor-pointer tj-db-filter-clear-icon"
onClick={() => {
setFilters({});
setTempFilters({});
}}
>
<SolidIcon name="remove" width="14px" fill="#3E63DD" />
</div>
)}
</div>
</OverlayTrigger>
</>
);

View file

@ -0,0 +1,72 @@
.filter-popup{
max-width: 560px !important;
min-height: 252px !important;
max-height: 420px !important;
border: 1px solid var(--border-weak) !important;
border-radius: 8px !important;
}
.filter-title{
display: flex;
align-items: center;
padding-left: 8px;
margin-bottom: 2px;
span{
font-family: IBM Plex Sans;
font-size: 12px;
font-weight: 500;
line-height: 18px;
text-align: left;
color: var(--text-default)
}
.width-lg{
width: 181.5px;
}
.width-sm{
width: 120px;
}
}
.filter-body{
padding: 24px 16px;
max-height: calc(420px - 56px - 64px);
overflow-y: auto;
scrollbar-gutter: stable;
position: relative;
.empty-filters-value{
border-radius: 6px;
padding: 10px;
text-align: center;
width: 100%;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
color: #687076;
font-size: 12px;
font-weight: 400;
line-height: 20px;
border: 1px dashed #E6E8EB;
}
&::-webkit-scrollbar{
display: none;
}
&:hover::-webkit-scrollbar{
display: block;
}
}
.filter-footer{
height: 64px;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
border-top: 1px solid var(--border-weak) !important;
}

View file

@ -1,11 +1,13 @@
import './styles.scss';
import React, { useContext, useEffect, useState } from 'react';
import Select from '@/_ui/Select';
import { TooljetDatabaseContext } from '../index';
import { operators } from '../constants';
import { debounce } from 'lodash';
import { ToolTip } from '@/_components';
import SolidIcon from '@/_ui/Icon/SolidIcons';
export const FilterForm = ({ filters, setFilters, index, column = '', operator = '', value = '' }) => {
export const FilterForm = ({ filters, setFilters, index, column = '', operator = '', value = '', generateMessage }) => {
const { columns, setPageCount } = useContext(TooljetDatabaseContext);
const [filterInputValue, setFilterInputValue] = useState(value);
@ -24,6 +26,10 @@ export const FilterForm = ({ filters, setFilters, index, column = '', operator =
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [filterInputValue]);
useEffect(() => {
setFilterInputValue(value);
}, [value]);
const handleColumnChange = (value) => {
const prevFilters = { ...filters };
prevFilters[index].column = value;
@ -45,37 +51,66 @@ export const FilterForm = ({ filters, setFilters, index, column = '', operator =
setPageCount(1);
};
const handleSelectOpen = () => {
document.body.classList.add('react-select-open');
const selectControl = document.querySelector('.select-operation-field .react-select__control');
if (selectControl) {
const rect = selectControl.getBoundingClientRect();
document.documentElement.style.setProperty('--select-width', `${rect.width}px`);
document.documentElement.style.setProperty('0', `${rect.left}px`);
document.documentElement.style.setProperty('100%', `${rect.bottom + window.scrollY}px`);
}
};
const handleSelectClose = () => {
document.body.classList.remove('react-select-open');
};
const displayColumns = columns.map(({ accessor }) => ({ value: accessor, label: accessor }));
return (
<div className="row g-2 align-items-center">
<div className="row g-0 d-flex align-items-center justify-content-center tw-w-[525px]">
<div className="col-11">
<div className="row g-2 align-items-center py-3">
<div className="col-4 select-column-field" data-cy="select-column-field">
<div className="row g-0 align-items-center">
<div className="col-4 select-column-field width-lg" data-cy="select-column-field">
<Select
useMenuPortal={false}
placeholder="Select column"
placeholder="Select.."
value={column}
options={displayColumns}
onChange={handleColumnChange}
width="100%"
borderRadius="8px 0px 0px 8px"
onMenuOpen={handleSelectOpen}
onMenuClose={handleSelectClose}
/>
</div>
<div className="col-4 select-operation-field" data-cy="select-operation-field">
<Select
placeholder="Select operation"
useMenuPortal={false}
value={operator}
options={operators}
onChange={handleOperatorChange}
/>
</div>
<ToolTip
message={generateMessage(operator)}
trigger={['hover']}
delay={{ show: '0', hide: '0' }}
show={['gt', 'lte', 'gte'].includes(operator)}
>
<div className="col-4 select-operation-field width-sm" data-cy="select-operation-field">
<Select
placeholder="Select.."
useMenuPortal={false}
value={operator}
options={operators}
onChange={handleOperatorChange}
width="100%"
borderRadius="0px"
onMenuOpen={handleSelectOpen}
onMenuClose={handleSelectClose}
/>
</div>
</ToolTip>
<div className="col-4">
<input
value={filterInputValue}
type="text"
className="form-control css-zz6spl-container"
className="form-control css-zz6spl-container input-element"
data-cy="value-input-field"
placeholder="Value"
placeholder="Enter value"
onChange={(event) => {
setFilterInputValue(event.target.value);
}}
@ -83,7 +118,7 @@ export const FilterForm = ({ filters, setFilters, index, column = '', operator =
</div>
</div>
</div>
<div className="col-1 cursor-pointer" data-cy="delete-icon" onClick={handleDelete}>
<div className="col-1 delete-icon-wrapper" data-cy="delete-icon" onClick={handleDelete}>
<SolidIcon name="trash" fill="#E54D2E" width="14" />
</div>
</div>

View file

@ -776,4 +776,92 @@
.tooltip-inner {
max-width: 100%;
}
.width-lg{
width: 181.5px;
}
.width-sm{
width: 120px;
}
.input-element{
width: 181.5px !important;
background-color: transparent !important;
color: var(--text-default) !important;
border-radius: 0px;
border: 1px solid var(--border-default) !important;
}
.delete-icon-wrapper{
display: flex;
align-items: center;
justify-content: center;
height: 32px;
width: 32px;
border: 1px solid var(--border-default);
border-radius: 0px 8px 8px 0px;
cursor: pointer;
border-left: none;
}
.select-operation-field{
.react-select__control{
.react-select__value-container{
position: relative;
.react-select__input-container{
position: absolute;
right: 0;
}
}
}
}
.select-operation-field,
.select-column-field{
position: static;
.react-select__control {
position: relative;
z-index: 2;
border-right: none !important;
}
.react-select__menu {
position: fixed;
z-index: 9999;
left: var(--select-left);
top: var(--select-top);
}
}
.select-column-field .react-select__menu {
width: 181.5px;
}
.select-operation-field .react-select__menu {
width: 120px;
}
body.react-select-open .filter-body {
pointer-events: none;
}
body.react-select-open .select-operation-field {
pointer-events: auto;
}
body.react-select-open .select-column-field {
pointer-events: auto;
}
.select-operation-field,
.select-column-field{
.react-select__menu{
.react-select__menu-list{
overflow-y: hidden;
&:hover {
overflow-y: auto;
}
}
}
}

View file

@ -36,6 +36,7 @@ const Header = ({
const darkMode = localStorage.getItem('darkMode') === 'true';
const [isAddNewDataMenuOpen, setIsAddNewDataMenuOpen] = useState(false);
const [bulkUploadFile, setBulkUploadFile] = useState(null);
const [activeFilters, setActiveFilters] = useState(0);
const [isBulkUploading, setIsBulkUploading] = useState(false);
const [errors, setErrors] = useState({ client: [], server: [] });
const [uploadResult, setUploadResult] = useState(null);
@ -173,7 +174,7 @@ const Header = ({
</ButtonSolid>
</span>
</AddNewDataPopOver>
<div style={{ width: '70px' }}>
<div style={{ width: '83px', marginRight: activeFilters > 0 ? '20px' : '0px' }}>
<Filter
filters={queryFilters}
setFilters={setQueryFilters}
@ -181,6 +182,7 @@ const Header = ({
resetFilterQuery={resetFilterQuery}
setFilterEnable={setFilterEnable}
filterEnable={filterEnable}
setActiveFilters={setActiveFilters}
/>
</div>
<div style={{ width: '70px' }}>

View file

@ -0,0 +1,361 @@
import React, { useEffect, useState } from 'react';
import { openapiService } from '@/_services';
import Select from '@/_ui/Select';
import { queryManagerSelectComponentStyle } from '@/_ui/Select/styles';
import DOMPurify from 'dompurify';
import { ToolTip } from '@/_components';
import CodeHinter from '@/AppBuilder/CodeEditor';
import { withTranslation } from 'react-i18next';
import { isEmpty } from 'lodash';
import PropTypes from 'prop-types';
import SolidIcons from '@/_ui/Icon/SolidIcons';
const operationColorMapping = {
get: 'azure',
post: 'green',
delete: 'red',
put: 'yellow',
};
const ApiEndpointInput = (props) => {
const [loadingSpec, setLoadingSpec] = useState(true);
const [options, setOptions] = useState(props.options);
const [specJson, setSpecJson] = useState(null);
const fetchOpenApiSpec = () => {
setLoadingSpec(true);
openapiService
.fetchSpecFromUrl(props.specUrl)
.then((response) => response.text())
.then((text) => {
const data = JSON.parse(text);
setSpecJson(data);
setLoadingSpec(false);
});
};
const changeOperation = (value) => {
const operation = value.split('/', 2)[0];
const path = value.substring(value.indexOf('/'));
const newOptions = { ...options, path, operation, selectedOperation: specJson.paths[path][operation] };
setOptions(newOptions);
props.optionsChanged(newOptions);
};
const changeParam = (paramType, paramName, value) => {
if (value === '') {
removeParam(paramType, paramName);
} else {
const newOptions = {
...options,
params: {
...options.params,
[paramType]: {
...options.params[paramType],
[paramName]: value,
},
},
};
setOptions(newOptions);
props.optionsChanged(newOptions);
}
};
const removeParam = (paramType, paramName) => {
const newOptions = JSON.parse(JSON.stringify(options));
delete newOptions['params'][paramType][paramName];
setOptions(newOptions);
props.optionsChanged(newOptions);
};
const renderOperationOption = (data) => {
const path = data.value.substring(data.value.indexOf('/'));
const operation = data.operation;
if (path && operation) {
return (
<div className="row">
<div className="col-auto" style={{ width: '60px' }}>
<span className={`badge bg-${operationColorMapping[operation]}`}>{operation}</span>
</div>
<div className="col">
<span>{path}</span>
</div>
</div>
);
} else {
return 'Select an operation';
}
};
const categorizeOperations = (operation, path, acc, category) => {
const option = {
value: `${operation}${path}`,
label: `${path}`,
name: path,
operation: operation,
};
const existingCategory = acc.find((obj) => obj.label === category);
if (existingCategory) {
existingCategory.options.push(option);
} else {
acc.push({
label: category,
options: [option],
});
}
};
const computeOperationSelectionOptions = () => {
const paths = specJson?.paths;
if (isEmpty(paths)) return [];
const pathGroups = Object.keys(paths).reduce((acc, path) => {
const operations = Object.keys(paths[path]);
const category = path.split('/')[2];
operations.forEach((operation) => categorizeOperations(operation, path, acc, category));
return acc;
}, []);
return pathGroups;
};
useEffect(() => {
const queryParams = {
path: props.options?.params?.path ?? {},
query: props.options?.params?.query ?? {},
request: props.options?.params?.request ?? {},
};
setLoadingSpec(true);
setOptions({ ...props.options, params: queryParams });
fetchOpenApiSpec();
}, []);
return (
<div>
{loadingSpec && (
<div className="p-3">
<div className="spinner-border spinner-border-sm text-azure mx-2" role="status"></div>
{props.t('stripe', 'Please wait while we load the OpenAPI specification.')}
</div>
)}
{options && !loadingSpec && (
<div>
<div className="d-flex g-2">
<div className="col-12 form-label">
<label className="form-label">{props.t('globals.operation', 'Operation')}</label>
</div>
<div className="col stripe-operation-options flex-grow-1" style={{ width: '90px', marginTop: 0 }}>
<Select
options={computeOperationSelectionOptions()}
value={{
operation: options?.operation,
value: `${options?.operation}${options?.path}`,
}}
onChange={(value) => changeOperation(value)}
width={'100%'}
useMenuPortal={true}
customOption={renderOperationOption}
styles={queryManagerSelectComponentStyle(props.darkMode, '100%')}
useCustomStyles={true}
/>
{options?.selectedOperation && (
<small
style={{ margintTop: '10px' }}
className="my-2"
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(options?.selectedOperation?.description) }}
/>
)}
</div>
</div>
{options?.selectedOperation && (
<div className={`row stripe-fields-row ${props.darkMode && 'theme-dark'}`}>
<RenderParameterFields
parameters={options?.selectedOperation?.parameters}
type="path"
label={props.t('globals.path', 'PATH')}
options={options}
changeParam={changeParam}
removeParam={removeParam}
darkMode={props.darkMode}
/>
<RenderParameterFields
parameters={options?.selectedOperation?.parameters}
type="query"
label={props.t('globals.query'.toUpperCase(), 'Query')}
options={options}
changeParam={changeParam}
removeParam={removeParam}
darkMode={props.darkMode}
/>
<RenderParameterFields
parameters={
options?.selectedOperation?.requestBody?.content[
Object.keys(options?.selectedOperation?.requestBody?.content)[0]
]?.schema?.properties ?? {}
}
type="request"
label={props.t('globals.requestBody', 'REQUEST BODY')}
options={options}
changeParam={changeParam}
removeParam={removeParam}
darkMode={props.darkMode}
/>
</div>
)}
</div>
)}
</div>
);
};
export default withTranslation()(ApiEndpointInput);
ApiEndpointInput.propTypes = {
options: PropTypes.object,
specUrl: PropTypes.string,
optionsChanged: PropTypes.func,
darkMode: PropTypes.bool,
t: PropTypes.func,
};
const RenderParameterFields = ({ parameters, type, label, options, changeParam, removeParam, darkMode }) => {
let filteredParams;
if (type === 'request') {
filteredParams = Object.keys(parameters);
} else {
filteredParams = parameters?.filter((param) => param.in === type);
}
const paramLabelWithDescription = (param) => {
return (
<ToolTip message={type === 'request' ? DOMPurify.sanitize(parameters[param].description) : param.description}>
<div className="cursor-help">
<input
type="text"
value={type === 'request' ? param : param.name}
className="form-control form-control-underline"
placeholder="key"
disabled
/>
</div>
</ToolTip>
);
};
const paramLabelWithoutDescription = (param) => {
return (
<input
type="text"
value={type === 'request' ? param : param.name}
className="form-control"
placeholder="key"
disabled
/>
);
};
const paramType = (param) => {
return (
<div className="p-2 text-muted">
{type === 'query' &&
param?.schema?.anyOf &&
param?.schema?.anyOf.map((type, i) =>
i < param.schema?.anyOf.length - 1
? type.type.substring(0, 3).toUpperCase() + '|'
: type.type.substring(0, 3).toUpperCase()
)}
{(type === 'path' || (type === 'query' && !param?.schema?.anyOf)) &&
param?.schema?.type?.substring(0, 3).toUpperCase()}
{type === 'request' && parameters[param].type?.substring(0, 3).toUpperCase()}
</div>
);
};
const paramDetails = (param) => {
return (
<div className="col-auto d-flex field field-width-179 align-items-center">
{(type === 'request' && parameters[param].description) || param?.description
? paramLabelWithDescription(param)
: paramLabelWithoutDescription(param)}
{param.required && <span className="text-danger fw-bold">*</span>}
{paramType(param)}
</div>
);
};
const inputField = (param) => {
return (
<CodeHinter
initialValue={(type === 'request' ? options?.params[type][param] : options?.params[type][param.name]) ?? ''}
mode="text"
placeholder={'Value'}
theme={darkMode ? 'monokai' : 'duotone-light'}
lineNumbers={false}
onChange={(value) => {
if (type === 'request') {
changeParam(type, param, value);
} else {
changeParam(type, param.name, value);
}
}}
height={'32px'}
/>
);
};
const clearButton = (param) => {
const handleClear = () => {
if (type === 'request') {
removeParam(type, param);
} else {
removeParam(type, param.name);
}
};
return (
<span
className="code-hinter-clear-btn"
role="button"
onClick={handleClear}
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleClear();
}
}}
tabIndex="0"
>
<SolidIcons name="removerectangle" width="20" fill="#ACB2B9" />
</span>
);
};
return (
filteredParams?.length > 0 && (
<div className={`${type === 'request' ? 'request-body' : type}-fields d-flex`}>
<h5 className="text-heading form-label">{label}</h5>
<div className="flex-grow-1 input-group-parent-container">
{filteredParams.map((param) => (
<div className="input-group-wrapper" key={type === 'request' ? param : param.name}>
<div className="input-group">
{paramDetails(param)}
<div className="col field overflow-hidden code-hinter-borderless">{inputField(param)}</div>
{((type === 'request' && options['params'][type][param]) || options['params'][type][param.name]) &&
clearButton(param)}
</div>
</div>
))}
</div>
</div>
)
);
};
RenderParameterFields.propTypes = {
parameters: PropTypes.any,
type: PropTypes.string,
label: PropTypes.string,
options: PropTypes.object,
changeParam: PropTypes.func,
removeParam: PropTypes.func,
darkMode: PropTypes.bool,
};

View file

@ -13,6 +13,7 @@ import CodeHinter from '@/AppBuilder/CodeEditor';
import GoogleSheets from '@/_components/Googlesheets';
import Slack from '@/_components/Slack';
import Zendesk from '@/_components/Zendesk';
import ApiEndpointInput from '@/_components/ApiEndpointInput';
import { ConditionFilter, CondtionSort, MultiColumn } from '@/_components/MultiConditions';
import Salesforce from '@/_components/Salesforce';
import ToolJetDbOperations from '@/AppBuilder/QueryManager/QueryEditors/TooljetDatabase/ToolJetDbOperations';
@ -219,6 +220,8 @@ const DynamicForm = ({
return ConditionFilter;
case 'sorts':
return CondtionSort;
case 'react-component-api-endpoint':
return ApiEndpointInput;
case 'react-component-salesforce':
return Salesforce;
case 'react-component-sharepoint':
@ -255,6 +258,7 @@ const DynamicForm = ({
encrypted,
placeholders = {},
editorType = 'basic',
specUrl = '',
disabled = false,
buttonText,
text,
@ -416,7 +420,15 @@ const DynamicForm = ({
darkMode,
optionsChanged,
};
case 'codehinter':
case 'codehinter': {
let theme;
if (darkMode) {
theme = 'monokai';
} else if (lineNumbers) {
theme = 'duotone-light';
} else {
theme = 'default';
}
return {
type: editorType,
initialValue: options[key]
@ -428,6 +440,7 @@ const DynamicForm = ({
lineNumbers,
className: className ? className : lineNumbers ? 'query-hinter' : 'codehinter-query-editor-input',
onChange: (value) => optionchanged(key, value),
theme: theme,
placeholder,
height,
width,
@ -436,6 +449,7 @@ const DynamicForm = ({
disabled,
delayOnChange: false,
};
}
case 'react-component-openapi-validator':
return {
format: options.format?.value,
@ -483,7 +497,13 @@ const DynamicForm = ({
onChange: (value) => optionchanged(key, value),
placeholders,
};
case 'react-component-api-endpoint':
return {
specUrl: specUrl,
optionsChanged,
options,
darkMode,
};
default:
return {};
}
@ -556,7 +576,8 @@ const DynamicForm = ({
{Object.keys(obj).map((key) => {
const { label, type, encrypted, className, key: propertyKey } = obj[key];
const Element = getElement(type);
const isSpecificComponent = ['tooljetdb-operations'].includes(type);
const isSpecificComponent = ['tooljetdb-operations', 'react-component-api-endpoint'].includes(type);
return (
<div
className={cx('my-2', {

View file

@ -54,7 +54,7 @@ export const OrganizationList = function () {
<div className={`align-items-center d-flex tj-org-dropdown ${darkMode && 'dark-theme'}`}>
{org.id === current_organization_id ? (
<div className="current-org-avatar">
<SolidIcon name="tick" fill="#3E63DD" dataCy="add-new-workspace-link" width="20" viewBox="0 0 17 15" />
<SolidIcon name="tick" fill="#3E63DD" data-cy="add-new-workspace-link" width="20" viewBox="0 0 17 15" />
</div>
) : (
<div
@ -79,7 +79,7 @@ export const OrganizationList = function () {
data-cy="current-org-indicator"
onClick={() => setShowEditOrg(true)}
>
<SolidIcon name="editable" fill="#3E63DD" dataCy="add-new-workspace-link" width="16" />
<SolidIcon name="editable" fill="#3E63DD" data-cy="edit-rectangle-icon" width="16" />
</div>
</ToolTip>
) : (

View file

@ -1474,5 +1474,6 @@ export const checkConditionsForRoute = (conditions, conditionsObj) => {
};
export const hasBuilderRole = (roleObj) => {
return roleObj.name === 'builder';
if (roleObj.name) return roleObj.name === 'builder';
return false;
};

View file

@ -228,7 +228,7 @@
.datasource-card {
height: 30px;
height: 122px !important;
height: 160px !important;
button {
display: none;
@ -307,6 +307,7 @@
.add-plugin-card{
border: 1px dashed var(--border-default, #CCD1D5);
background-color: var(--interactive-weak);
height: 160px;
&:hover{
border: 1px dashed var(--border-strong, #CCD1D5);
@ -334,4 +335,36 @@
background-color: var(--interactive-default);
}
}
}
}
.card-tag{
position: relative;
left: 85px;
bottom: 10px;
}
.tag{
flex-direction: row;
align-items: center;
padding: 1px 7px;
width: 38px;
height: 18px;
background: linear-gradient(271.34deg, rgba(255, 95, 109, 0.12) -88.47%, rgba(255, 195, 113, 0.12) 94.89%);
border-radius: 100px;
.p{
background: linear-gradient(96.1deg, #FF5F6D -15.44%, #FFC371 99.37%);
}
}
.ee-gradient-text {
background: linear-gradient(96.1deg, #FF5F6D -15.44%, #FFC371 99.37%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 11px;
font-weight: 500;
line-height: 16px;
margin-top: 0px;
margin-bottom: 0px;
}

View file

@ -814,6 +814,16 @@ $border-radius: 4px;
overflow: hidden;
.input-group {
.code-hinter-borderless {
.code-hinter-wrapper {
border-right-width: 0 !important;
}
}
.code-hinter-clear-btn {
padding: 5px 10px 5px 6px;
}
.field {
.form-control {
height: 32px;
@ -825,6 +835,12 @@ $border-radius: 4px;
line-height: 20px;
}
.form-control-underline {
text-decoration: underline;
text-decoration-style: dashed;
text-underline-offset: 2.5px;
}
.code-hinter-col {
margin-bottom: 0 !important;

View file

@ -7012,6 +7012,25 @@ input.hide-input-arrows {
}
}
.filter-header{
width: 100%;
height: 56px;
padding: 0 24px;
display: flex;
align-items: center;
justify-content: space-between;
color: var(--text-default);
border-bottom: 1px solid var(--border-weak);
.filter-heading{
font-family: IBM Plex Sans;
font-size: 14px;
font-weight: 500;
line-height: 20px;
text-align: left;
}
}
tbody {
width: 100% !important;
flex-grow: 1;
@ -7869,6 +7888,7 @@ tbody {
border-right: 1px solid var(--slate5) !important;
display: grid !important;
grid-template-rows: auto 1fr auto !important;
position: fixed;
}
.home-page-sidebar {
@ -10410,6 +10430,7 @@ tbody {
.tj-db-filter-btn {
width: 100%;
height: 28px;
display: flex;
border-radius: 6px;
background: transparent;
color: var(--slate12);
@ -10431,6 +10452,20 @@ tbody {
border-radius: 6px !important;
}
.tj-db-filter-btn-applied,
.tj-db-filter-clear-icon{
background-color: var(--indigo4) !important;
color: var(--indigo9) !important;
&:hover{
background-color: var(--button-secondary-pressed) !important;
}
}
.tj-db-filter-clear-icon{
border-radius: 0px 6px 6px 0px;
}
.tj-db-filter-btn-active,
.tj-db-sort-btn-active {
display: flex !important;
@ -10444,6 +10479,23 @@ tbody {
color: var(--indigo9) !important;
}
.tj-db-filter-btn-active{
background: var(--button-outline-pressed) !important;
color: var(--text-default) !important;
}
.tj-db-filter-btn-active-filter{
display: flex !important;
flex-direction: row !important;
justify-content: center !important;
align-items: center !important;
width: 100% !important;
height: 28px !important;
border-radius: 6px !important;
background: var(--button-secondary-pressed) !important;
color: var(--text-brand) !important;
}
.tj-db-header-add-new-row-btn {
height: 28px;
background: transparent;
@ -13076,6 +13128,26 @@ color: var(--text-default);
}
}
.tag-container{
width: 38px;
height: 18px;
background: linear-gradient(271.34deg, rgba(255, 95, 109, 0.12) -88.47%, rgba(255, 195, 113, 0.12) 94.89%);
border-radius: 100px;
display: flex;
align-items: center;
justify-content: center;
padding: 1px 7px;
span{
font-size: 11px;
line-height: 16px;
font-weight: 500;
background: linear-gradient(96.1deg, #FF5F6D -15.44%, #FFC371 99.37%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.template-source-name {
color: var(--slate12) !important;
}
@ -16027,7 +16099,7 @@ color: var(--text-default);
}
}
div.ds-svg-container svg {
div.ds-svg-container img {
padding: 2px;
}

View file

@ -0,0 +1,12 @@
import React from 'react';
import Icon from '@/_ui/Icon/SolidIcons';
function AiBanner({ className }) {
return (
<div className={`d-flex tag ${className}`}>
<Icon name="AI-tag" />
<p className="ee-gradient-text">AI</p>
</div>
);
}
export default AiBanner;

View file

@ -105,6 +105,11 @@
background: var(--indigo9);
}
&:disabled {
background: var(--button-primary-disabled) !important;
color: var(--text-disabled-on-solid) !important;
border: none !important;
}
}
.tj-zBlack-btn {

View file

@ -1,6 +1,7 @@
import React from 'react';
// eslint-disable-next-line import/no-unresolved
import { allSvgs } from '@tooljet/plugins/client';
import AiBanner from '@/_ui/AiBanner';
const Card = ({
title,
@ -13,6 +14,7 @@ const Card = ({
titleClassName,
actionButton,
darkMode,
tags = [],
}) => {
const DisplayIcon = ({ src }) => {
if (typeof src !== 'string') return;
@ -44,7 +46,8 @@ const Card = ({
data-cy={`data-source-${String(title).toLocaleLowerCase()}`}
>
<div className="card-body">
<center>
{tags && tags.includes('AI') && <AiBanner className="card-tag" />}
<center style={{ marginTop: tags.length > 0 ? '0px' : '15px' }}>
<DisplayIcon src={src} />
<br></br>
<br></br>

View file

@ -0,0 +1,34 @@
import React from 'react';
const AITag = ({ fill = 'none', width = '12', height = '12', className = '', viewBox = '0 0 12 12' }) => {
return (
<svg
width={width}
height={height}
fill={fill}
className={className}
viewBox={viewBox}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.36783 5.99998C4.31182 7.02317 5.28234 8.16244 5.99999 11C6.71764 8.16244 7.68814 7.02317 10.6321 5.99998C7.68814 4.97686 6.71764 3.83759 5.99999 1C5.28234 3.83759 4.31182 4.97686 1.36783 5.99998Z"
fill="url(#paint0_linear_654_1335)"
/>
<defs>
<linearGradient
id="paint0_linear_654_1335"
x1="11.5717"
y1="-5.5"
x2="-0.0865091"
y2="-4.34623"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#FF5F6D" />
<stop offset="1" stopColor="#FFC371" />
</linearGradient>
</defs>
</svg>
);
};
export default AITag;

View file

@ -174,6 +174,7 @@ import Search01 from './Search01.jsx';
import ShiftButtonIcon from './ShiftButtonIcon.jsx';
import Unpin01 from './Unpin01.jsx';
import WarningUserNotFound from './WarningUserNotFound.jsx';
import AITag from './AITag.jsx';
import Reset from './Reset.jsx';
const Icon = (props) => {
@ -530,6 +531,8 @@ const Icon = (props) => {
return <TriangleUpCenter {...props} />;
case 'TriangleDownCenter':
return <TriangleDownCenter {...props} />;
case 'AI-tag':
return <AITag {...props} />;
default:
return <Apps {...props} />;
}

View file

@ -29,9 +29,10 @@ export const SelectComponent = ({
menuPlacement = 'auto',
useCustomStyles = false,
isDisabled = false,
borderRadius,
} = restProps;
const customStyles = useCustomStyles ? styles : defaultStyles(isDarkMode, width, height, styles);
const customStyles = useCustomStyles ? styles : defaultStyles(isDarkMode, width, height, styles, borderRadius);
const selectOptions =
Array.isArray(options) && options.length === 0
? options

View file

@ -1,5 +1,5 @@
/* eslint-disable no-unused-vars */
export default function styles(darkMode, width = 224, height = 32, styles = {}) {
export default function styles(darkMode, width = 224, height = 32, styles = {}, borderRadius) {
return {
container: (provided) => ({
...provided,
@ -26,6 +26,7 @@ export default function styles(darkMode, width = 224, height = 32, styles = {})
height: height,
minHeight: height,
cursor: styles.cursor ?? 'pointer',
...(borderRadius ? { borderRadius } : {}),
}),
valueContainer: (provided, state) => ({
...provided,

View file

@ -21,8 +21,12 @@ const ForgotPasswordInfoScreen = ({ email }) => {
<div className="forgot-password-info-wrapper info-screen">
<OnboardingUIWrapper>
<FormHeader>{t('forgotPasswordInfo.header', 'Check your mail')}</FormHeader>
<p className="message">{message}</p>
<span className="info">{info}</span>
<p className="message" data-cy="onboarding-page-description">
{message}
</p>
<span className="info" data-cy="info-message">
{info}
</span>
<SepratorComponent />
<div className="action-buttons">
<button onClick={() => navigate('/login')} className="back-to-login-button" data-cy="back-to-login">

View file

@ -129,7 +129,7 @@ const LoginForm = ({
<>
{' '}
{signupText}{' '}
<Link to={signUpUrl} className="signin-link" tabIndex="-1" data-cy="signin-link">
<Link to={signUpUrl} className="signin-link" tabIndex="-1" data-cy="create-an-account-link">
{t('createToolJetAccount', signUpCTA)}
</Link>
</>

View file

@ -17,7 +17,9 @@ const ForgotPasswordInfoScreen = ({ email }) => {
<div className="forgot-password-info-wrapper info-screen">
<OnboardingUIWrapper>
<FormHeader>Password has been reset</FormHeader>
<p className="message">{message}</p>
<p className="message" data-cy="reset-password-page-description">
{message}
</p>
<div className="action-buttons pt-3">
<button
onClick={() =>

View file

@ -4,7 +4,9 @@ import './resources/styles/form-description.styles.scss';
const FormDescription = ({ children: View }) => {
return (
<>
<p className="onboarding-form-description">{View}</p>
<p className="onboarding-form-description" data-cy="onboarding-page-description">
{View}
</p>
</>
);
};

View file

@ -1,12 +1,13 @@
import React from 'react';
const FormHeader = ({ children: View, styles, dataCy }) => {
const defaultDataCy = View?.toString()?.toLowerCase().replace(/\s+/g, '-');
const computedDataCy = dataCy || defaultDataCy;
return (
<>
<h2 className="form-header" style={styles} data-cy={dataCy}>
{View}
</h2>
</>
<h2 className="form-header" style={styles} data-cy={`${computedDataCy}-header`}>
{View}
</h2>
);
};

Some files were not shown because too many files have changed in this diff Show more