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

feat: insert link plugin tinymce #455

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
53ce3a6
feat: insert link plugin tinymce
johnvente Jan 18, 2024
e9dee15
test: adding more test unit for insert link modal
johnvente Jan 18, 2024
15f00a8
test: adding test for insertlinkmodaltoggle hook
johnvente Jan 18, 2024
2dcc8a6
test: some tests for formatblocks util
johnvente Jan 18, 2024
214ea4d
test: more test for insertlinkmodal component
johnvente Jan 18, 2024
173e9f3
test: adding more coverage for insertlinkmodal components
johnvente Jan 19, 2024
3eebebb
refactor: subsectios name for blocklist component
johnvente Jan 19, 2024
9cd8d8b
fix: remove enzyme for tests
johnvente Jan 22, 2024
b7b42e6
refactor: remove blank line
johnvente Jan 24, 2024
c963cfa
refactor: moving utils to their components and url validation
johnvente Feb 15, 2024
efc7dc8
chore: upgrade with main branch
johnvente Feb 15, 2024
dc14183
fix: changing exd to openedx modules
johnvente Feb 15, 2024
64cb44e
fix: tests for filterblock updated and config for tests
johnvente Feb 15, 2024
18c0802
feat: adding prefix for http https urls and translations for insert link
johnvente Feb 16, 2024
fa00def
fix: solve conflicts
johnvente Feb 20, 2024
08b1e75
refactor: removing confirmlinkformatalert for urls
johnvente Feb 20, 2024
71172ae
fix: limit insert link only for course sections
johnvente Feb 22, 2024
095aa67
fix: handling no selected text for jum to
johnvente Feb 29, 2024
7055c2b
fix: disable tooltip with no selected text and external url edge case
johnvente Mar 15, 2024
a8c88b5
fix: jump to link edition
johnvente Apr 2, 2024
b11bf08
fix: removing delete jump to link
johnvente Apr 2, 2024
b5b40b4
feat: adding support for editing a selected link
johnvente Apr 5, 2024
989b538
fix: test for shared components
johnvente Apr 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"fast-xml-parser": "^4.0.10",
"frontend-components-tinymce-advanced-plugins": "^1.0.3",
"lodash-es": "^4.17.21",
"lodash.clonedeep": "^4.5.0",
"lodash.flatten": "^4.4.0",
"moment": "^2.29.4",
"moment-shortformat": "^2.1.0",
Expand Down
1 change: 1 addition & 0 deletions src/editors/data/constants/tinyMCE.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const buttons = StrictDict({
undo: 'undo',
underline: 'underline',
a11ycheck: 'a11ycheck',
insertLink: 'insertlink',
embediframe: 'embediframe',
});

Expand Down
2 changes: 2 additions & 0 deletions src/editors/data/redux/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as requests from './requests';
import * as video from './video';
import * as problem from './problem';
import * as game from './game';
import * as insertlink from './insertlink';

/* eslint-disable import/no-cycle */
export { default as thunkActions } from './thunkActions';
Expand All @@ -17,6 +18,7 @@ const modules = {
video,
problem,
game,
insertlink,
};

const moduleProps = (propName) => Object.keys(modules).reduce(
Expand Down
2 changes: 2 additions & 0 deletions src/editors/data/redux/insertlink/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { actions, reducer } from './reducers';
export { default as selectors } from './selectors';
27 changes: 27 additions & 0 deletions src/editors/data/redux/insertlink/reducers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { createSlice } from '@reduxjs/toolkit';
import { StrictDict } from '../../../utils';

const initialState = {
selectedBlocks: {},
};

// eslint-disable-next-line no-unused-vars
const insertlink = createSlice({
name: 'insertlink',
initialState,
reducers: {
addBlock: (state, { payload }) => {
state.selectedBlocks = { ...state.selectedBlocks, ...payload };
},
},
});

const actions = StrictDict(insertlink.actions);

const { reducer } = insertlink;

export {
actions,
initialState,
reducer,
};
28 changes: 28 additions & 0 deletions src/editors/data/redux/insertlink/reducers.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { reducer, actions, initialState } from './reducers';

describe('insertlink reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {})).toEqual(initialState);
});

it('should handle addBlock', () => {
const payload = {
block123: { id: 'block123', content: 'Block 123 content' },
block456: { id: 'block456', content: 'Block 456 content' },
};
const action = actions.addBlock(payload);

const previousState = {
selectedBlocks: { block789: { id: 'block789', content: 'Block 789 content' } },
};

const expectedState = {
selectedBlocks: {
...previousState.selectedBlocks,
...payload,
},
};

expect(reducer(previousState, action)).toEqual(expectedState);
});
});
5 changes: 5 additions & 0 deletions src/editors/data/redux/insertlink/selectors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const insertlinkState = (state) => state.insertlink;

export default {
insertlinkState,
};
19 changes: 19 additions & 0 deletions src/editors/data/redux/insertlink/selectors.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { insertlinkState } from './selectors';

describe('insertlink selectors', () => {
describe('insertlinkState selector', () => {
it('should return the insertlink slice of the state', () => {
const state = {
insertlink: {
selectedBlocks: {
block123: { id: 'block123', url: 'https://www.example.com' },
block456: { id: 'block456', url: 'https://www.example.com' },
},
},
};

const { selectedBlocks } = insertlinkState(state);
expect(selectedBlocks).toEqual(state.insertlink.selectedBlocks);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`BlockLink Component snapshot 1`] = `
<div>
<div
class="link-container d-flex row p-4 rounded border border-gray-400 mx-4 mt-3"
>
<div
class="col-10"
>
<p
class="text-left"
/>
<p
class="h2 w-20 title"
>
Some Path
</p>
</div>
<div
class="col-2"
>
<button
class="d-flex justify-content-center align-items-center"
data-testid="close-link-button"
variant="tertiary"
>
 
</button>
</div>
</div>
</div>
`;
37 changes: 37 additions & 0 deletions src/editors/sharedComponents/InsertLinkModal/BlockLink/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import PropTypes from 'prop-types';
import { Button } from '@openedx/paragon';
import { LinkOff } from '@openedx/paragon/icons';
import formatBlockPath from '../formatBlockPath';

import './index.scss';

const BlockLink = ({ path, onCloseLink }) => {
const { title, subTitle } = formatBlockPath(path);
return (
<div className="link-container d-flex row p-4 rounded border border-gray-400 mx-4 mt-3">
<div className="col-10">
<p className="text-left">{subTitle}</p>
<p className="h2 w-20 title">{title}</p>
</div>
<div className="col-2">
<Button
variant="tertiary"
className="d-flex justify-content-center align-items-center"
data-testid="close-link-button"
size="lg"
iconBefore={LinkOff}
onClick={onCloseLink}
>
&nbsp;
</Button>
</div>
</div>
);
};

BlockLink.propTypes = {
path: PropTypes.string.isRequired,
onCloseLink: PropTypes.func.isRequired,
};

export default BlockLink;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.link-container {
.title {
overflow-wrap: break-word;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { render, fireEvent, screen } from '@testing-library/react';
import '@testing-library/jest-dom';

import formatBlockPath from '../formatBlockPath';
import BlockLink from './index';

describe('BlockLink Component', () => {
const defaultProps = {
path: 'Some Path',
onCloseLink: jest.fn(),
};

const renderComponent = (overrideProps = {}) => render(
<BlockLink {...defaultProps} {...overrideProps} />,
);

test('renders with default props', () => {
renderComponent();
expect(screen.getByText('Some Path')).toBeInTheDocument();
});

test('snapshot', () => {
const { container } = renderComponent();
expect(container).toMatchSnapshot();
});

test('renders correctly with custom path', () => {
const customProps = {
...defaultProps,
path: 'Custom Path',
};
renderComponent(customProps);
expect(screen.getByText('Custom Path')).toBeInTheDocument();
});

test('calls onCloseLink when the button is clicked', () => {
renderComponent();
fireEvent.click(screen.getByTestId('close-link-button'));
expect(defaultProps.onCloseLink).toHaveBeenCalledTimes(1);
});

test('renders with valid title and subtitle', () => {
const customProps = {
path: 'Root Section / Child 1',
onCloseLink: jest.fn(),
};

renderComponent(customProps);
const { title, subTitle } = formatBlockPath(customProps.path);

expect(screen.getByText(title)).toBeInTheDocument();
expect(screen.getByText(subTitle)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`BlocksList Component snapshot 1`] = `
<div>
<div
class="block-list-container"
>
<div
class="pgn-transition-replace-group position-relative"
>
<div
style="padding: .1px 0px;"
>
<div
class="w-100 d-flex justify-content-space-between p-3 pgn__action-row"
>
<button
class="col-11 py-4 btn btn-tertiary"
data-testid="block-name"
type="button"
>
<span
class="w-100 text-left"
>
Any display name
</span>
</button>
<button
class="col-1 py-4 btn btn-tertiary"
data-testid="block-navigation"
type="button"
>

<span
class="pgn__icon btn-icon-after"
>
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="24"
role="img"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m6.49 20.13 1.77 1.77 9.9-9.9-9.9-9.9-1.77 1.77L14.62 12l-8.13 8.13Z"
fill="currentColor"
/>
</svg>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
`;
Loading
Loading