Fix browser extension field sort order (#1473)

This commit is contained in:
Leendert de Borst
2026-01-23 17:42:53 +01:00
parent 897026d6ff
commit 6dbd832d69
11 changed files with 30 additions and 22 deletions

View File

@@ -199,17 +199,7 @@ const ItemDetails: React.FC = (): React.ReactElement => {
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
{t('common.credentials')}
</h2>
{/* Sort login fields: email first, then username, then password, then others */}
{[...groupedFields[FieldCategories.Login]].sort((a, b) => {
const order: Record<string, number> = {
'login.email': 0,
'login.username': 1,
'login.password': 2
};
const aOrder = order[a.FieldKey] ?? 99;
const bOrder = order[b.FieldKey] ?? 99;
return aOrder - bOrder;
}).map((field) => (
{groupedFields[FieldCategories.Login].map((field) => (
<FieldBlock key={field.FieldKey} field={field} itemId={item.Id} />
))}
</div>

View File

@@ -116,7 +116,7 @@ export class FieldMapper {
FieldType: systemField?.FieldType || FieldTypes.Text,
IsHidden: systemField?.IsHidden ? 1 : 0,
Value: row.Value,
DisplayOrder: row.DisplayOrder,
DisplayOrder: systemField?.DefaultDisplayOrder ?? row.DisplayOrder,
IsCustomField: false,
EnableHistory: systemField?.EnableHistory ?? false
};
@@ -173,7 +173,7 @@ export class FieldMapper {
Label: row.FieldKey, // Use FieldKey as label; UI layer translates via fieldLabels.*
FieldType: systemField?.FieldType || FieldTypes.Text,
IsHidden: systemField?.IsHidden ? 1 : 0,
DisplayOrder: row.DisplayOrder,
DisplayOrder: systemField?.DefaultDisplayOrder ?? row.DisplayOrder,
IsCustomField: false,
EnableHistory: systemField?.EnableHistory ?? false
});

View File

@@ -23,7 +23,7 @@ declare const ItemTypeIconSvgs: {
* Placeholder key icon for Login/Alias items without a logo.
* Traditional key design with outline style.
*/
readonly Placeholder: "<svg viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"6.5\" stroke=\"#f49541\" stroke-width=\"2.5\"/>\n <circle cx=\"10\" cy=\"10\" r=\"2.5\" stroke=\"#f49541\" stroke-width=\"2\"/>\n <path d=\"M15 15L27 27\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M19 19L23 15\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M24 24L28 20\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n</svg>";
readonly Placeholder: "<svg viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"6.5\" fill=\"none\" stroke=\"#f49541\" stroke-width=\"2.5\"/>\n <circle cx=\"10\" cy=\"10\" r=\"2.5\" fill=\"none\" stroke=\"#f49541\" stroke-width=\"2\"/>\n <path d=\"M15 15L27 27\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M19 19L23 15\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M24 24L28 20\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n</svg>";
/**
* Note/document icon with folded corner.
* Used for Note item type.

View File

@@ -9,8 +9,8 @@ var ItemTypeIconSvgs = {
* Traditional key design with outline style.
*/
Placeholder: `<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="10" cy="10" r="6.5" stroke="#f49541" stroke-width="2.5"/>
<circle cx="10" cy="10" r="2.5" stroke="#f49541" stroke-width="2"/>
<circle cx="10" cy="10" r="6.5" fill="none" stroke="#f49541" stroke-width="2.5"/>
<circle cx="10" cy="10" r="2.5" fill="none" stroke="#f49541" stroke-width="2"/>
<path d="M15 15L27 27" stroke="#f49541" stroke-width="2.5" stroke-linecap="round"/>
<path d="M19 19L23 15" stroke="#f49541" stroke-width="2.5" stroke-linecap="round"/>
<path d="M24 24L28 20" stroke="#f49541" stroke-width="2.5" stroke-linecap="round"/>

View File

@@ -354,6 +354,7 @@ declare function hasField(item: Item, fieldKey: string): boolean;
declare function groupFields(item: Item, grouper: (field: ItemField) => string): Record<string, ItemField[]>;
/**
* Group fields by standard categories (Login, Alias, Card, Notes, Custom)
* Fields within each category are sorted by DisplayOrder.
*/
declare function groupFieldsByCategory(item: Item): Record<string, ItemField[]>;
/**

View File

@@ -366,7 +366,7 @@ function groupFields(item, grouper) {
return groups;
}
function groupFieldsByCategory(item) {
return groupFields(item, (field) => {
const groups = groupFields(item, (field) => {
if (field.FieldKey.startsWith("login.")) {
return FieldCategories.Login;
}
@@ -384,6 +384,10 @@ function groupFieldsByCategory(item) {
}
return FieldCategories.Custom;
});
for (const category of Object.keys(groups)) {
groups[category].sort((a, b) => (a.DisplayOrder ?? 0) - (b.DisplayOrder ?? 0));
}
return groups;
}
function itemToCredential(item) {
return {

View File

@@ -23,7 +23,7 @@ declare const ItemTypeIconSvgs: {
* Placeholder key icon for Login/Alias items without a logo.
* Traditional key design with outline style.
*/
readonly Placeholder: "<svg viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"6.5\" stroke=\"#f49541\" stroke-width=\"2.5\"/>\n <circle cx=\"10\" cy=\"10\" r=\"2.5\" stroke=\"#f49541\" stroke-width=\"2\"/>\n <path d=\"M15 15L27 27\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M19 19L23 15\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M24 24L28 20\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n</svg>";
readonly Placeholder: "<svg viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"6.5\" fill=\"none\" stroke=\"#f49541\" stroke-width=\"2.5\"/>\n <circle cx=\"10\" cy=\"10\" r=\"2.5\" fill=\"none\" stroke=\"#f49541\" stroke-width=\"2\"/>\n <path d=\"M15 15L27 27\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M19 19L23 15\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <path d=\"M24 24L28 20\" stroke=\"#f49541\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n</svg>";
/**
* Note/document icon with folded corner.
* Used for Note item type.

View File

@@ -9,8 +9,8 @@ var ItemTypeIconSvgs = {
* Traditional key design with outline style.
*/
Placeholder: `<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="10" cy="10" r="6.5" stroke="#f49541" stroke-width="2.5"/>
<circle cx="10" cy="10" r="2.5" stroke="#f49541" stroke-width="2"/>
<circle cx="10" cy="10" r="6.5" fill="none" stroke="#f49541" stroke-width="2.5"/>
<circle cx="10" cy="10" r="2.5" fill="none" stroke="#f49541" stroke-width="2"/>
<path d="M15 15L27 27" stroke="#f49541" stroke-width="2.5" stroke-linecap="round"/>
<path d="M19 19L23 15" stroke="#f49541" stroke-width="2.5" stroke-linecap="round"/>
<path d="M24 24L28 20" stroke="#f49541" stroke-width="2.5" stroke-linecap="round"/>

View File

@@ -354,6 +354,7 @@ declare function hasField(item: Item, fieldKey: string): boolean;
declare function groupFields(item: Item, grouper: (field: ItemField) => string): Record<string, ItemField[]>;
/**
* Group fields by standard categories (Login, Alias, Card, Notes, Custom)
* Fields within each category are sorted by DisplayOrder.
*/
declare function groupFieldsByCategory(item: Item): Record<string, ItemField[]>;
/**

View File

@@ -366,7 +366,7 @@ function groupFields(item, grouper) {
return groups;
}
function groupFieldsByCategory(item) {
return groupFields(item, (field) => {
const groups = groupFields(item, (field) => {
if (field.FieldKey.startsWith("login.")) {
return FieldCategories.Login;
}
@@ -384,6 +384,10 @@ function groupFieldsByCategory(item) {
}
return FieldCategories.Custom;
});
for (const category of Object.keys(groups)) {
groups[category].sort((a, b) => (a.DisplayOrder ?? 0) - (b.DisplayOrder ?? 0));
}
return groups;
}
function itemToCredential(item) {
return {

View File

@@ -60,9 +60,10 @@ export function groupFields(
/**
* Group fields by standard categories (Login, Alias, Card, Notes, Custom)
* Fields within each category are sorted by DisplayOrder.
*/
export function groupFieldsByCategory(item: Item): Record<string, ItemField[]> {
return groupFields(item, (field) => {
const groups = groupFields(item, (field) => {
if (field.FieldKey.startsWith('login.')) {
return FieldCategories.Login;
}
@@ -80,6 +81,13 @@ export function groupFieldsByCategory(item: Item): Record<string, ItemField[]> {
}
return FieldCategories.Custom;
});
// Sort fields within each category by DisplayOrder
for (const category of Object.keys(groups)) {
groups[category].sort((a, b) => (a.DisplayOrder ?? 0) - (b.DisplayOrder ?? 0));
}
return groups;
}
/**