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

1945 Links to projects, subprojects #2025

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 frontend/src/languages/english.js
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,12 @@ const en = {
select: "Select a picture from the gallery or upload a custom picture"
},

clipboard: {
copy: "Copy link",
copied: "Link copied",
paste: "Paste link"
},

language: {
english: "English",
french: "French",
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/languages/french.js
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,12 @@ const fr = {
select: "Sélectionner ou télécharger une image personnalisée"
},

clipboard: {
copy: "Copier le lien",
copied: "Lien copié",
paste: "Coller le lien"
},

language: {
english: "Anglais",
french: "Français",
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/languages/georgian.js
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,12 @@ const ka = {
select: "აირჩიეთ სურათი გალერეიდან ან ატვირთეთ მორგებული სურათი."
},

clipboard: {
copy: "დააკოპირეთ ბმული",
copied: "ბმული კოპირებულია",
paste: "ჩასვით ლინკი"
},

language: {
english: "ინგლისური",
french: "ფრანგული",
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/languages/german.js
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,12 @@ const de = {
select: "Wählen Sie ein Bild aus oder laden Sie ein eigenes hoch"
},

clipboard: {
copy: "Link kopieren",
copied: "Link kopiert",
paste: "Link einfügen"
},

language: {
english: "Englisch",
french: "Französisch",
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/languages/portuguese.js
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,12 @@ const pt = {
select: "Selecione ou faça o upload de uma imagem personalizada"
},

clipboard: {
copy: "Copiar link",
copied: "Link copiado",
paste: "Colar link"
},

language: {
english: "English",
french: "Français",
Expand Down
63 changes: 42 additions & 21 deletions frontend/src/pages/Common/Markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,60 @@ import React from "react";
import {
BoldItalicUnderlineToggles,
CreateLink,
headingsPlugin,
linkDialogPlugin,
linkPlugin,
listsPlugin,
ListsToggle,
MDXEditor,
quotePlugin,
toolbarPlugin,
UndoRedo
} from "@mdxeditor/editor";

import strings from "../../localizeStrings";

import "@mdxeditor/editor/style.css";

const Markdown = ({ text, onChangeFunc }) => {
const Markdown = ({ text, onChangeFunc, readOnly, paste, clipboard }) => {
const ref = React.useRef(null);
return (
<MDXEditor
markdown={text || ""}
onChange={onChangeFunc}
plugins={[
toolbarPlugin({
toolbarContents: () => (
<>
{" "}
<UndoRedo />
<BoldItalicUnderlineToggles />
<ListsToggle />
<CreateLink />
</>
)
}),
linkDialogPlugin(),
listsPlugin(),
linkPlugin()
]}
/>
<>
{clipboard ? (
<button
onClick={() => {
ref.current?.focus(() => ref.current?.insertMarkdown(clipboard));
paste();
}}
>
{strings.clipboard.paste}
</button>
) : null}
<MDXEditor
ref={ref}
markdown={text || ""}
onChange={onChangeFunc}
readOnly={readOnly}
plugins={[
headingsPlugin(),
listsPlugin(),
linkDialogPlugin(),
linkPlugin(),
quotePlugin(),
toolbarPlugin({
toolbarContents: () => (
<>
{" "}
<UndoRedo />
<BoldItalicUnderlineToggles />
<ListsToggle />
<CreateLink />
</>
)
})
]}
/>
</>
);
};

Expand Down
16 changes: 16 additions & 0 deletions frontend/src/pages/Navbar/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export const SAVE_EMAIL_ADDRESS_SUCCESS = "SAVE_EMAIL_ADDRESS_SUCCESS";
export const SAVE_EMAIL_ADDRESS_FAILED = "SAVE_EMAIL_ADDRESS_FAILED";
export const SET_VALID_EMAIL_ADDRESS_INPUT = "SET_VALID_EMAIL_ADDRESS_INPUT";

export const CLIPBOARD_COPY = "CLIPBOARD_COPY";
export const CLIPBOARD_PASTE = "CLIPBOARD_PASTE";

export function toggleSidebar() {
return {
type: TOGGLE_SIDEBAR
Expand Down Expand Up @@ -144,3 +147,16 @@ export function setValidEmailAddressInput(valid) {
valid
};
}

export function clipboardCopy(text) {
return {
type: CLIPBOARD_COPY,
text
};
}

export function clipboardPaste() {
return {
type: CLIPBOARD_PASTE
};
}
11 changes: 10 additions & 1 deletion frontend/src/pages/Navbar/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
import { FETCH_ALL_SUBPROJECT_DETAILS_SUCCESS } from "../Workflows/actions";

import {
CLIPBOARD_COPY,
CLIPBOARD_PASTE,
DISABLE_USER_PROFILE_EDIT,
ENABLE_USER_PROFILE_EDIT,
FETCH_ACTIVE_PEERS_SUCCESS,
Expand Down Expand Up @@ -40,7 +42,8 @@ const defaultState = fromJS({
userProfileOpen: false,
userProfileEdit: false,
tempEmailAddress: "",
isEmailAddressInputValid: true
isEmailAddressInputValid: true,
clipboard: null
});

export default function navbarReducer(state = defaultState, action) {
Expand Down Expand Up @@ -100,6 +103,12 @@ export default function navbarReducer(state = defaultState, action) {
searchTerm: defaultState.get("searchTerm"),
searchBarDisplayed: defaultState.get("searchBarDisplayed")
});
case CLIPBOARD_COPY: {
return state.set("clipboard", action.text || "");
}
case CLIPBOARD_PASTE: {
return state.set("clipboard", null);
}
default:
return state;
}
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/pages/Overview/ProjectDialogContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { connect } from "react-redux";

import { toJS } from "../../helper";
import withInitialLoading from "../Loading/withInitialLoading";
import { clipboardPaste } from "../Navbar/actions";
import { storeSnackbarMessage } from "../Notifications/actions";

import {
Expand Down Expand Up @@ -38,7 +39,8 @@ const mapStateToProps = (state) => {
currentStep: state.getIn(["overview", "currentStep"]),
projectToAdd: state.getIn(["overview", "projectToAdd"]),
dialogTitle: state.getIn(["overview", "dialogTitle"]),
allowedIntents: state.getIn(["login", "allowedIntents"])
allowedIntents: state.getIn(["login", "allowedIntents"]),
clipboard: state.getIn(["navbar", "clipboard"])
};
};

Expand All @@ -61,7 +63,8 @@ const mapDispatchToProps = (dispatch) => {
addProjectTag: (tag) => dispatch(addProjectTag(tag)),
removeProjectTag: (tag) => dispatch(removeProjectTag(tag)),
addCustomImage: (imageBase64) => dispatch(addCustomImage(imageBase64)),
removeCustomImage: (imageBase64) => dispatch(removeCustomImage(imageBase64))
removeCustomImage: (imageBase64) => dispatch(removeCustomImage(imageBase64)),
pasteClipboard: () => dispatch(clipboardPaste())
};
};

Expand Down
8 changes: 7 additions & 1 deletion frontend/src/pages/Overview/ProjectDialogContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ const ProjectDialogContent = (props) => {
<Divider />
<div>
<Typography variant="subtitle2">{strings.project.markdown}</Typography>
<Markdown onChangeFunc={props.storeProjectMarkdown} text={props.projectToAdd.markdown} />
<Markdown
onChangeFunc={props.storeProjectMarkdown}
text={props.projectToAdd.markdown}
clipboard={props.clipboard}
paste={props.pasteClipboard}
readOnly={false}
/>
</div>
</div>
);
Expand Down
37 changes: 33 additions & 4 deletions frontend/src/pages/SubProjects/SubProjectContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import _isEqual from "lodash/isEqual";
import queryString from "query-string";

import ContentAdd from "@mui/icons-material/Add";
import ContentPasteIcon from "@mui/icons-material/ContentPaste";
import { IconButton } from "@mui/material";
import { Fab, Typography } from "@mui/material";

import { toJS } from "../../helper";
Expand All @@ -17,8 +19,8 @@ import AdditionalInfo from "../Common/AdditionalInfo";
import worker from "../Common/filterProjects.worker.js";
import LiveUpdates from "../LiveUpdates/LiveUpdates";
import { fetchUser } from "../Login/actions";
import { setSelectedView } from "../Navbar/actions";
import { hideHistory, openHistory } from "../Notifications/actions";
import { clipboardCopy, setSelectedView } from "../Navbar/actions";
import { hideHistory, openHistory, showSnackbar, storeSnackbarMessage } from "../Notifications/actions";

import {
closeProject,
Expand Down Expand Up @@ -77,6 +79,16 @@ class SubProjectContainer extends Component {
}

componentDidUpdate(prevProps) {
if (this.props.router.location.pathname !== prevProps.router.location.pathname) {
const newProjectId = this.props.router.location.pathname.split("/")[2];
if (newProjectId !== this.projectId) {
this.setState({ isDataFetched: false });
this.projectId = newProjectId;
this.props.setSelectedView(this.projectId, "project");
this.props.fetchAllProjectDetails(this.projectId, true);
this.setState({ isDataFetched: true });
}
}
const searchTermChanges = this.props.searchTerm !== prevProps.searchTerm;
const projectsChange = !_isEqual(this.props.subProjects, prevProps.subProjects);

Expand Down Expand Up @@ -127,6 +139,19 @@ class SubProjectContainer extends Component {
<div />
) : (
<div>
<>
<IconButton
onClick={() => {
this.props.clipboardCopy(`[${this.props.projectName}](${this.props.router.location.pathname})`);
this.props.storeSnackbarMessage(strings.clipboard.copied);
this.props.showSnackbar();
}}
data-test={`project-copy-button-${projectId}`}
size="small"
>
<ContentPasteIcon />
</IconButton>
</>
<ProjectDetails
{...this.props}
projectId={projectId}
Expand Down Expand Up @@ -188,7 +213,10 @@ const mapDispatchToProps = (dispatch) => {
storeSubSearchTerm: (subSearchTerm) => dispatch(storeSubSearchTerm(subSearchTerm)),
storeSubSearchBarDisplayed: (subSearchBarDisplayed) => dispatch(storeSubSearchBarDisplayed(subSearchBarDisplayed)),
storeFilteredSubProjects: (filteredSubProjects) => dispatch(storeFilteredSubProjects(filteredSubProjects)),
storeSubSearchTermArray: (searchTerms) => dispatch(storeSubSearchTermArray(searchTerms))
storeSubSearchTermArray: (searchTerms) => dispatch(storeSubSearchTermArray(searchTerms)),
clipboardCopy: (text) => dispatch(clipboardCopy(text)),
showSnackbar: () => dispatch(showSnackbar()),
storeSnackbarMessage: (message) => dispatch(storeSnackbarMessage(message))
};
};

Expand Down Expand Up @@ -221,7 +249,8 @@ const mapStateToProps = (state) => {
searchTerms: state.getIn(["detailview", "searchTerms"]),
idsPermissionsUnassigned: state.getIn(["detailview", "idsPermissionsUnassigned"]),
isDataLoading: state.getIn(["loading", "loadingVisible"]),
isLiveUpdatesProjectEnabled: state.getIn(["detailview", "isLiveUpdatesProjectEnabled"])
isLiveUpdatesProjectEnabled: state.getIn(["detailview", "isLiveUpdatesProjectEnabled"]),
clipboard: state.getIn(["navbar", "clipboard"])
};
};

Expand Down
Loading