Skip to content

Commit

Permalink
feat(explorer): do not close truncated parts
Browse files Browse the repository at this point in the history
  • Loading branch information
alber70g committed Dec 20, 2024
1 parent 6354c5c commit f08fc16
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 52 deletions.
8 changes: 8 additions & 0 deletions .changeset/soft-tomatoes-know.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@kadena/explorer': patch
---

Reordering columns to present the first column as the one to link to

Remove toggling close of truncated content. Will always open so users can no
select and copy
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CopyButton } from '@/components/CopyButton/CopyButton';
import { Stack, Text } from '@kadena/kode-ui';
import classNames from 'classnames';
import type { FC } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import React, { useState } from 'react';
import {
descriptionDetailsClass,
descriptionDetailsExpandedClass,
Expand All @@ -14,57 +14,12 @@ interface IProps {
field: IDataRenderComponentField;
}

const storageKey = 'expandedfields';

export const ExpandTruncatedField: FC<IProps> = ({ field }) => {
const [isExpanded, setIsExpanded] = useState(false);

const toggleExpand = (): void => {
let storage: string[] = JSON.parse(
localStorage.getItem(storageKey) ?? '[]',
);

const key = field.key ? field.key : field.id ?? '';

if (isExpanded) {
storage = storage.filter((v) => v !== key);
} else {
storage.push(key);
}

localStorage.setItem(storageKey, JSON.stringify(storage));

window.dispatchEvent(new Event(storageKey));
setIsExpanded((v) => !isExpanded);
};

const checkStorage = () => {
const storage: string[] = JSON.parse(
localStorage.getItem(storageKey) ?? '[]',
);

setIsExpanded(storage.includes(field.key));
};
const storageListener = useCallback((event: StorageEvent | Event) => {
if (event.type !== storageKey && 'key' in event && event.key !== storageKey)
return;

checkStorage();
}, []);

useEffect(() => {
checkStorage();
window.addEventListener(storageKey, storageListener);
window.addEventListener('storage', storageListener);
return () => {
window.removeEventListener(storageKey, storageListener);
window.removeEventListener('storage', storageListener);
};
}, [storageListener]);

return (
<Stack
onClick={toggleExpand}
onClick={() => setIsExpanded(true)}
as="dd"
gap="xs"
className={classNames(descriptionDetailsClass, {
Expand Down
79 changes: 79 additions & 0 deletions packages/apps/explorer/src/utils/__test__/condenseString.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { condenseStrings } from '../condenseStrings';

describe('condenseString', () => {
const singleWord =
'thisisaverylongstringthatshouldbecondensedthisisaverylongstringthatshouldbecondensed';
const multiWord =
'thisisaverylongstringthatshouldbecond ensedthisisaverylongstringthatshouldbecondensed thisIsAshorterString';

describe('with default options', () => {
it('condenses a single string', () => {
expect(condenseStrings(singleWord)).toBe('thisi…ensed');
});

it('condenses a string with multiple words', () => {
expect(condenseStrings(multiWord)).toBe(
'thisi…econd ensed…ensed thisIsAshorterString',
);
});
});
describe('with custom options', () => {
it('minLength 10', () => {
expect(condenseStrings(singleWord, { minLength: 10 })).toBe(
'thisi…ensed',
);
expect(condenseStrings(multiWord, { minLength: 10 })).toBe(
'thisi…econd ensed…ensed thisI…tring',
);
});

it('replacement "..."', () => {
expect(condenseStrings(singleWord, { replacement: '...' })).toBe(
'thisi...ensed',
);
expect(condenseStrings(multiWord, { replacement: '...' })).toBe(
'thisi...econd ensed...ensed thisIsAshorterString',
);
});

it('startLength 10', () => {
expect(condenseStrings(singleWord, { startLength: 10 })).toBe(
'thisisaver…ensed',
);
expect(condenseStrings(multiWord, { startLength: 10 })).toBe(
'thisisaver…econd ensedthisi…ensed thisIsAshorterString',
);
});

it('endLength 10', () => {
expect(condenseStrings(singleWord, { endLength: 10 })).toBe(
'thisi…econdensed',
);
expect(condenseStrings(multiWord, { endLength: 10 })).toBe(
'thisi…ouldbecond ensed…econdensed thisIsAshorterString',
);
});

it('all options', () => {
expect(
condenseStrings(singleWord, {
minLength: 40,
replacement: '*.*',
startLength: 5,
endLength: 20,
}),
).toBe('thisi*.*hatshouldbecondensed');

expect(
condenseStrings(multiWord, {
minLength: 40,
replacement: '*.*',
startLength: 5,
endLength: 20,
}),
).toBe(
'thisisaverylongstringthatshouldbecond ensed*.*hatshouldbecondensed thisIsAshorterString',
);
});
});
});
32 changes: 27 additions & 5 deletions packages/apps/explorer/src/utils/condenseStrings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,39 @@
* @param str - string to shorten
* @returns {[string, string]} - shortened string and original string
*/
export function condenseStrings(str: string) {
export function condenseStrings(
str: string,
options?: {
minLength?: number;
replacement?: string;
startLength?: number;
endLength?: number;
},
): string {
// set default options and override with provided options
let config;
if (options) {
config = {
...{ minLength: 22, replacement: '…', startLength: 5, endLength: 5 },
...options,
};
} else {
config = {
minLength: 22,
replacement: '…',
startLength: 5,
endLength: 5,
};
}

// Regex explanation:
// Split on sequences of characters that are NOT letters, digits, '_' or '-'.
const parts = str.split(/([^\w\d]+)/u);

console.log(parts);

return parts
.map((part) => {
if (/^[\w\d]+$/u.test(part) && part.length > 22) {
return `${part.slice(0, 5)}${part.slice(-5)}`;
if (/^[\w\d]+$/u.test(part) && part.length > config.minLength) {
return `${part.slice(0, config.startLength)}${config.replacement}${part.slice(-config.endLength)}`;
}
return part;
})
Expand Down

0 comments on commit f08fc16

Please sign in to comment.