Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENG-808: Add custom handler functions support to OXD profile pic & link cell types #798

Merged
merged 9 commits into from
Nov 4, 2024
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
2024-11-01 - d9cb67f8abf3c1128203f14bce687c8b5b4075a6 - Remove unnecessary separator between consecutive page numbers in OXD pagination

2024-11-01 - 5f4c5306a8ec4b497cb824fa673e50ac0162af4b - ProfilePicture.vue, ProfilePic.vue, profile-pic.spec.ts- add onclick event to prevent default behaviour of link and execute a function fix issue

2024-11-01 - 891d531ac92cf7e3bcced8c018a7f7fd2efe6bb9 - Icons.ts - add external link icon

2024-10-28 - e5840791366e3abbf3cb6b57f77ede4a8842fb79 - Icon/icons.ts - Add oxd-date-input, oxd-attachment-input,oxd-checkbox-input, oxd-checkbox-group-input, oxd-select-input, oxd-file-input, oxd-radio-input, oxd-radio-group-input, oxd-switch-input, oxd-time-input, oxd-text-input, oxd-password-input, oxd-circle-plus, oxd-textbox, oxd-text, oxd-divider, oxd-grid, oxd-grid-item, oxd-subform, oxd-masterdata, oxd-employee-autocomplete, oxd-status, oxd-required to OXD Icons

2024-10-26 - a7f234223a3a34e55a77e3c216733c9f01e5e3c9 - directives/focus-first-element/index.ts - Update the focus first directive to wait for animations to stop
Expand Down
18 changes: 17 additions & 1 deletion components/src/core/components/CardTable/Cell/LinkWithPill.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
<oxd-skeleton width="50%" animate></oxd-skeleton>
</template>
<template v-else>
<a :href="link ? row[link] : '#'" :target="target" :class="linkClasses">
<a
:href="link ? row[link] : '#'"
:target="target"
:class="linkClasses"
@click="handleLinkClick(row, $event)"
>
{{ cell }}
</a>
<div v-if="pillProperty" :class="pillClasses">
Expand Down Expand Up @@ -45,6 +50,13 @@ export default defineComponent({
}
return value;
},
handleLinkClick(row: RowItem, event: MouseEvent) {
const cellConfig = this.header?.cellConfig;
if (cellConfig && typeof cellConfig?.onClick === 'function') {
event.preventDefault();
this.header.cellConfig.onClick(row, event);
}
},
},
props: {
link: {
Expand All @@ -70,6 +82,10 @@ export default defineComponent({
type: Boolean,
default: false,
},
header: {
type: Object,
default: () => ({}),
},
},
computed: {
linkClasses(): object {
Expand Down
18 changes: 18 additions & 0 deletions components/src/core/components/CardTable/Cell/ProfilePicture.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
:link="profilePicture.link"
:imageSrc="profilePicture.src"
:link-mode="profilePicture.target"
:link-handler="handleLinkClick"
v-bind="$attrs"
/>
</template>
Expand Down Expand Up @@ -52,6 +53,14 @@ export default defineComponent({
type: Boolean,
default: false,
},
header: {
type: Object,
default: () => ({}),
},
rowItem: {
type: Object,
default: () => ({}),
},
},
setup(props) {
const imgSrc = ref(null);
Expand Down Expand Up @@ -87,13 +96,22 @@ export default defineComponent({

const isLoading = computed(() => props.loading || imgLoading.value);

const handleLinkClick = (event: MouseEvent) => {
const cellConfig = props.header?.cellConfig;
if (cellConfig && typeof cellConfig?.onClick === 'function') {
event.preventDefault();
props.header?.cellConfig.onClick(props.rowItem, event);
}
};

watchEffect(async () => {
imgSrc.value = await loadImage(props.item as string);
});

return {
isLoading,
profilePicture,
handleLinkClick,
};
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,54 @@ describe('CardTable > Cell > LinkWithPill.vue', () => {
.trim(),
).toEqual('external');
});

it('should trigger handleLinkClick on link click', async () => {
const mockOnClick = jest.fn();
const rowItem = {
url1: 'https://orangehrm.com',
tag: 'external',
};

const wrapper = mount(LinkWithPill, {
global: GLOBAL,
props: {
item: 'This is a link',
target: '_parent',
link: 'url1',
rowItem: rowItem,
header: {
cellConfig: {
onClick: mockOnClick,
},
},
},
});

const link = wrapper.find('a');
await link.trigger('click');

expect(mockOnClick).toHaveBeenCalledWith(rowItem, expect.any(MouseEvent));
});

it('should not prevent default behavior if no onClick handler is present', async () => {
const wrapper = mount(LinkWithPill, {
global: GLOBAL,
props: {
item: 'This is a link',
target: '_blank',
link: 'url1',
rowItem: {
url1: 'https://orangehrm.com',
tag: 'external',
},
},
});

const link = wrapper.find('a');
const event = {preventDefault: jest.fn()};

await link.trigger('click', event);

expect(event.preventDefault).not.toHaveBeenCalled();
});
});
6 changes: 6 additions & 0 deletions components/src/core/components/Icon/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,11 @@ export const oxdRequired: icon = {
</svg>`,
};

export const oxdExternalLink: icon = {
name: 'oxd-external-link',
value: `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"/><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/><g id="SVGRepo_iconCarrier"><g id="Interface / External_Link"><path id="Vector" style="fill:none" d="M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></g></g></svg>`,
DanuAnjana marked this conversation as resolved.
Show resolved Hide resolved
};

const icons: Icons = {
'oxd-likes': oxdLikes,
'oxd-birthday': oxdBirthday,
Expand Down Expand Up @@ -2350,6 +2355,7 @@ const icons: Icons = {
'oxd-employee-autocomplete': oxdEmployeeAutocomplete,
'oxd-status': oxdStatus,
'oxd-required': oxdRequired,
'oxd-external-link': oxdExternalLink,
};

export default icons;
19 changes: 18 additions & 1 deletion components/src/core/components/ProfilePic/ProfilePic.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
<template>
<div :class="classes">
<slot>
<a v-if="link" :href="link" :target="linkMode">
<a
v-if="link"
:href="link"
:target="linkMode"
@click="handleLinkClick($event)"
>
<span
class="img-tag"
:style="`background-image: url(${profileImage})`"
Expand Down Expand Up @@ -29,6 +34,7 @@ import {
import {defaultUser} from './images';
export default defineComponent({
name: 'oxd-profile-pic',

props: {
size: {
type: String,
Expand All @@ -55,6 +61,17 @@ export default defineComponent({
return TARGETS.indexOf(value) !== -1;
},
},
linkHandler: {
type: Function,
required: false,
},
},
methods: {
handleLinkClick(event: MouseEvent) {
if (this.linkHandler && typeof this.linkHandler === 'function') {
this.linkHandler(event);
}
},
},
computed: {
classes(): object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,19 @@ describe('ProfilePic.vue', () => {
});
expect(wrapper.html()).toMatchSnapshot();
});

it('should call linkHandler with event payload on link click when linkHandler is provided', async () => {
const mockLinkHandler = jest.fn();
const wrapper = mount(ProfilePic, {
props: {
link: 'https://orangehrm.com',
linkHandler: mockLinkHandler,
},
});

const link = wrapper.find('a');
await link.trigger('click');

expect(mockLinkHandler).toHaveBeenCalledWith(expect.any(MouseEvent));
});
});
43 changes: 43 additions & 0 deletions storybook/stories/core/components/ListTable/ListSkeleton.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
:skeleton="showSkeleton"
v-model:selected="checkedItems"
></oxd-list-table>
<br />
<p>{{ LinkPhillResult }}</p>
<br/>
<p>{{ profilePicResult }}</p>
</template>

<script>
Expand All @@ -30,6 +34,8 @@ export default {

data() {
return {
LinkPhillResult: '',
profilePicResult: '',
selector: {
style: {flex: 1},
},
Expand All @@ -44,6 +50,23 @@ export default {
iconStyle: 'color: #929baa; justify-content: center;',
cellType: 'oxd-table-cell-profile-pic',
},
{
name: 'profilePic',
style: {
width: '55px',
'justify-content': 'center',
},
iconName: 'oxd-profile-pic',
iconStyle: 'color: #929baa; justify-content: center;',
cellType: 'oxd-table-cell-profile-pic',
cellProps: {
link: "url1",
target: "_blank",
},
cellConfig: {
onClick: this.onClickProfilePic,
},
},
{
name: 'col1',
sortField: 'col1.name',
Expand Down Expand Up @@ -71,6 +94,20 @@ export default {
pillProperty: ['tag', 'name'],
},
},
{
name: 'col2',
title: 'Link with Pill with onClick event',
style: {flex: 1},
cellType: 'oxd-table-cell-link-with-pill',
cellProps: {
link: 'url1',
target: '_blank',
pillProperty: ['tag', 'name'],
},
cellConfig: {
onClick: this.onClickLinkWithPill,
},
},
{
name: 'col4',
title: 'Date',
Expand Down Expand Up @@ -116,6 +153,12 @@ export default {
},
};
},
onClickLinkWithPill(row, event) {
this.LinkPhillResult = 'Link with Pill with onClick function executed: ' + row.col2;
},
onClickProfilePic(row, event) {
this.profilePicResult = 'Profile Pic with onClick function executed: ' + row.col2;
},
},

beforeMount() {
Expand Down
Loading