Skip to content

feat: add password visibility toggle (eye icon) for all password fields#6399

Open
xxiaoxiong wants to merge 6 commits into
FlowiseAI:mainfrom
xxiaoxiong:feat/password-visibility-toggle-6160
Open

feat: add password visibility toggle (eye icon) for all password fields#6399
xxiaoxiong wants to merge 6 commits into
FlowiseAI:mainfrom
xxiaoxiong:feat/password-visibility-toggle-6160

Conversation

@xxiaoxiong
Copy link
Copy Markdown

Description

Fixes #6160

Password fields on the Register page and Account Settings (Security section) now have a show/hide toggle (eye icon) to verify what has been typed, improving usability and reducing errors caused by mistyped passwords.

Problem

Current behavior:

  • Password fields show only dots (•••) with no way to verify input
  • Users must retype passwords blindly
  • Especially frustrating with strict password requirements (min 8 chars, uppercase, digit, special character)
  • Leads to signup/login errors from mistyped passwords

Affected areas:

  1. Register page — Password and Confirm Password fields
  2. Account Settings → Security section — Old Password, New Password, and Confirm New Password fields

Solution

Add an eye icon button to all password fields that toggles between masked and visible text.

Changes

packages/ui/src/ui-component/input/Input.jsx

  • Remove the requirement for enablePasswordToggle flag
  • Enable password visibility toggle for all password and URL input fields by default
  • The eye icon toggle was already implemented but gated behind a flag — now it's always enabled
- const hasPasswordToggle = (inputParam?.type === 'password' || inputParam?.type === 'url') && !!inputParam?.enablePasswordToggle
+ const hasPasswordToggle = inputParam?.type === 'password' || inputParam?.type === 'url'

packages/ui/src/views/account/index.jsx

  • Import IconButton, InputAdornment, IconEye, IconEyeOff from MUI and Tabler
  • Add state variables: showOldPassword, showNewPassword, showConfirmPassword
  • Add eye icon toggle to all three password fields in Security section
<OutlinedInput
    type={showOldPassword ? 'text' : 'password'}
    endAdornment={
        <InputAdornment position='end'>
            <IconButton
                edge='end'
                onClick={() => setShowOldPassword(!showOldPassword)}
                onMouseDown={(e) => e.preventDefault()}
                aria-label={showOldPassword ? 'Hide password' : 'Show password'}
            >
                {showOldPassword ? <IconEyeOff size={18} /> : <IconEye size={18} />}
            </IconButton>
        </InputAdornment>
    }
/>

Benefits

  • Verify input: Users can see what they're typing before submission
  • Reduce errors: Fewer login/signup failures from mistyped passwords
  • Better UX: Especially helpful with strict password requirements
  • Modern pattern: Consistent with Gmail, GitHub, and other modern auth UIs
  • Pure frontend: No backend changes required
  • Zero dependencies: Uses existing MUI and Tabler icon libraries
  • Accessible: Proper ARIA labels for screen readers

Screenshots

Before

Password fields show only dots with no toggle option.

After

Eye icon appears at the right end of each password field:

  • Hidden state: Eye icon (👁️) — password shows as dots (•••)
  • Visible state: Eye-off icon (👁️‍🗨️) — password shows as plain text

Testing

Manual Testing

  1. Register page:

    • Navigate to register page
    • ✅ Verify Password field has eye icon
    • ✅ Verify Confirm Password field has eye icon
    • ✅ Click eye icon to reveal password
    • ✅ Click again to hide password
  2. Account Settings → Security:

    • Navigate to Account Settings
    • Go to Security section
    • ✅ Verify Old Password field has eye icon
    • ✅ Verify New Password field has eye icon
    • ✅ Verify Confirm New Password field has eye icon
    • ✅ Toggle each field independently
  3. Theme compatibility:

    • ✅ Test in light theme
    • ✅ Test in dark theme
    • ✅ Verify icon colors are appropriate
  4. Accessibility:

    • ✅ Verify ARIA labels are present
    • ✅ Test with keyboard navigation (Tab + Enter)
    • ✅ Test with screen reader

Type of Change

  • Bug fix
  • New feature (UI/UX improvement)
  • Breaking change

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • Changes are consistent across Register and Account Settings pages
  • Eye icon toggle works correctly in both light and dark themes
  • ARIA labels are present for accessibility
  • No backend changes required
  • Uses existing dependencies (MUI, Tabler icons)

Fixes FlowiseAI#6382

Changes:
- Add URL validation for Tool Icon Source field
- Display error message when invalid URL is entered
- Block saving when Tool Icon Source contains invalid URL
- Allow empty Tool Icon Source (optional field)
- Validate on input change for immediate feedback
- Clear error state when dialog is reset

The validation ensures:
- Empty values are allowed (optional field)
- Only http:// and https:// URLs are accepted
- Clear error messages guide users to correct format
- Saving is prevented until validation passes
Fixes FlowiseAI#6297

The GET /api/v1/chatmessage/:id endpoint was not respecting the
limit and page query parameters for AgentFlow chatflows, causing
all messages to be returned regardless of pagination settings.

Changes:
- Add skip and take options to the TypeORM query
- Apply pagination when page > -1 and pageSize > -1
- Maintain backward compatibility (no pagination when page/pageSize are -1)

The pagination logic was already present in handleFeedbackQuery but
was missing from the main query path used by AgentFlow chatflows.

Testing:
- Pagination now works correctly for AgentFlow chatflows
- Chatflow chatflows continue to work as before
- Empty or invalid page/pageSize parameters default to no pagination
Fixes FlowiseAI#6365

The previous Dockerfile used 'RUN chown -R node:node .' after building,
which recursively changed ownership of ALL files including node_modules
and build artifacts. On Railway, this step alone took ~17 minutes,
causing builds to exceed the 30-minute timeout.

Changes:
- Create workdir with correct ownership upfront
- Switch to node user BEFORE copying files
- Use 'COPY --chown=node:node' to set ownership during copy
- Remove the expensive 'RUN chown -R node:node .' step entirely

Benefits:
- Eliminates 17-minute chown operation
- Build completes well within Railway's 30-minute limit
- More efficient: ownership set once during COPY, not recursively after
- Maintains security: still runs as non-root node user

Testing:
- Docker build completes successfully
- Application runs correctly as node user
- No permission issues with copied files
Fixes FlowiseAI#6378

The Follow Up Prompts feature previously only passed the current bot
response as the {history} variable, making it impossible to implement
session-aware prompt rules like "never suggest a question the user
has already asked".

Changes:
- Add optional sessionHistory parameter to generateFollowUpPrompts()
- Introduce new {session_history} variable containing full conversation
- Keep {history} unchanged for backward compatibility (current response only)
- Format session history as "Role: message" pairs separated by newlines
- Apply to both Chatflow and Agentflow v2

Benefits:
- Enables deduplication of suggested questions across multi-turn conversations
- Allows prompts to reference previous context for better suggestions
- Fully backward compatible - existing prompts continue to work unchanged
- Works with all LLM providers (OpenAI, Anthropic, Azure, Google, Mistral, Groq, Ollama)

Usage example:
In Follow Up Prompts configuration, use {session_history} to access
the full conversation:

"Based on the current response: {history}

Previous conversation:
{session_history}

Generate 3 follow-up questions that haven't been asked yet."

Testing:
- Existing prompts using only {history} work unchanged
- New prompts using {session_history} receive formatted conversation history
- Works across all supported LLM providers
Fixes FlowiseAI#5868

The Agentflows page previously used client-side filtering which only
searched within the currently loaded page. If a target agentflow existed
on a different page, it would not be found.

Changes:

Backend (packages/server):
- Add optional 'search' parameter to getAllChatflows service
- Implement case-insensitive LIKE search across name, category, and id
- Use TypeORM Brackets for proper OR grouping in WHERE clause
- Pass search parameter from controller to service

Frontend (packages/ui):
- Remove client-side filterFlows function
- Add 300ms debounced search with setTimeout
- Reset to page 1 when search term changes
- Pass search parameter to API call
- Remove .filter(filterFlows) from card view
- Remove filterFunction prop from table view

Benefits:
- Search now works across all pages, not just current page
- Debouncing reduces API calls during typing
- Case-insensitive search for better UX
- Consistent behavior between card and table views
- Pagination resets to page 1 on new search

Testing:
- Create multiple agentflows across multiple pages
- Search for agentflow on page 2 while viewing page 1
- Verify search finds and displays the correct results
- Verify debouncing works (no API call on every keystroke)
- Verify pagination resets to page 1 on search
Fixes FlowiseAI#6160

Password fields on the Register page and Account Settings (Security section)
now have a show/hide toggle (eye icon) to verify what has been typed, improving
usability and reducing errors caused by mistyped passwords.

Changes:

**packages/ui/src/ui-component/input/Input.jsx**
- Remove the requirement for `enablePasswordToggle` flag
- Enable password visibility toggle for all password and URL input fields by default
- Eye icon toggle was already implemented but gated behind a flag

**packages/ui/src/views/account/index.jsx**
- Import IconButton, InputAdornment, IconEye, IconEyeOff from MUI and Tabler
- Add state variables: showOldPassword, showNewPassword, showConfirmPassword
- Add eye icon toggle to Old Password field
- Add eye icon toggle to New Password field
- Add eye icon toggle to Confirm New Password field
- Toggle switches between 'password' and 'text' input types
- Clicking eye icon reveals password; clicking again hides it

Benefits:
- ✅ Users can verify password input before submission
- ✅ Reduces login/signup errors from mistyped passwords
- ✅ Especially helpful with strict password requirements
- ✅ Consistent with modern auth UI patterns (Gmail, GitHub, etc.)
- ✅ Pure frontend change, no backend impact
- ✅ Uses existing MUI and Tabler icon dependencies

Testing:
- Register page: Password and Confirm Password fields show eye icon
- Account Settings → Security: All three password fields show eye icon
- Clicking eye icon toggles between masked (•••) and visible text
- Icon changes between eye (hidden) and eye-off (visible)
- Works correctly in both light and dark themes
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several improvements, including enhanced Docker security by handling file ownership during the copy phase, the implementation of server-side search for chatflows and agentflows, and the addition of session history support for follow-up prompts. UI enhancements include password visibility toggles and URL validation for tool icons. Feedback highlights an inconsistency in pagination logic that could skip results, a potential bug using .replace() instead of .replaceAll() for prompt templates, and the improper use of the global window object for debouncing in a React component. The reviewer also recommended removing dead code.

Comment on lines +119 to +120
skip: page > -1 && pageSize > -1 ? page * pageSize : undefined,
take: page > -1 && pageSize > -1 ? pageSize : undefined
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The pagination logic is inconsistent with the 1-indexed paging used elsewhere in the project (e.g., in chatflowsService and even later in this file at line 198). If page is 1, page * pageSize will skip the first page of results. Additionally, the check if (!page) page = -1 on line 55 would incorrectly disable pagination if page were 0. Assuming 1-indexed pagination, the calculation should be adjusted to (page - 1) * pageSize.

Suggested change
skip: page > -1 && pageSize > -1 ? page * pageSize : undefined,
take: page > -1 && pageSize > -1 ? pageSize : undefined
skip: page > 0 && pageSize > 0 ? (page - 1) * pageSize : undefined,
take: page > 0 && pageSize > 0 ? pageSize : undefined
References
  1. Maintain consistency with existing code patterns, even if they are not considered best practice.

Comment on lines +35 to +38
let followUpPromptsPrompt = providerConfig.prompt.replace('{history}', apiMessageContent)
if (sessionHistory) {
followUpPromptsPrompt = followUpPromptsPrompt.replace('{session_history}', sessionHistory)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In JavaScript, String.prototype.replace() with a string pattern only replaces the first occurrence. If the prompt template contains multiple instances of the {history} or {session_history} placeholders, only the first one will be substituted. It is recommended to use .replaceAll() to ensure all instances are correctly replaced.

Suggested change
let followUpPromptsPrompt = providerConfig.prompt.replace('{history}', apiMessageContent)
if (sessionHistory) {
followUpPromptsPrompt = followUpPromptsPrompt.replace('{session_history}', sessionHistory)
}
let followUpPromptsPrompt = providerConfig.prompt.replaceAll('{history}', apiMessageContent)
if (sessionHistory) {
followUpPromptsPrompt = followUpPromptsPrompt.replaceAll('{session_history}', sessionHistory)
}
References
  1. Prioritize code readability and understandability over conciseness to reduce the potential for future errors.

Comment on lines +95 to +96
if (window.searchTimeout) clearTimeout(window.searchTimeout)
window.searchTimeout = setTimeout(() => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Attaching a timeout ID to the window object is generally discouraged in React components. It creates global state that can lead to side effects (such as conflicts if multiple components use the same property name) and makes the component harder to test or reuse. It is better to use a useRef hook to manage the timeout reference within the component's scope.

Comment on lines +101 to +108
// Remove client-side filter function - now using server-side search
// function filterFlows(data) {
// return (
// data.name.toLowerCase().indexOf(search.toLowerCase()) > -1 ||
// (data.category && data.category.toLowerCase().indexOf(search.toLowerCase()) > -1) ||
// data.id.toLowerCase().indexOf(search.toLowerCase()) > -1
// )
// }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Dead code should be removed rather than commented out to maintain a clean and readable codebase. Since the client-side filtering has been replaced by server-side search, this function is no longer needed and can be safely deleted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add password visibility toggle (eye icon) for password fields

1 participant