From ba5018ec3a4893062981def9c430cacaa09bac0e Mon Sep 17 00:00:00 2001 From: "Marcel S. Henselin" Date: Wed, 21 Sep 2022 16:27:00 +0200 Subject: [PATCH 1/3] Update Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 98bff78..d4b5b6d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,10 @@ -FROM golang:alpine +FROM golang:1.15-alpine WORKDIR /src RUN apk add --update npm git RUN go get -u github.com/jteeuwen/go-bindata/... COPY ./webapp/package.json webapp/package.json RUN cd ./webapp && \ - npm install + npm ci COPY . . RUN cd ./webapp && \ npm run build From 151ac107f096b7af843e234a8845660485f71f63 Mon Sep 17 00:00:00 2001 From: "Marcel S. Henselin" Date: Wed, 21 Sep 2022 16:29:39 +0200 Subject: [PATCH 2/3] Update Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index d4b5b6d..4b995f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ WORKDIR /src RUN apk add --update npm git RUN go get -u github.com/jteeuwen/go-bindata/... COPY ./webapp/package.json webapp/package.json +COPY ./webapp/package-lock.json webapp/package-lock.json RUN cd ./webapp && \ npm ci COPY . . From f38838923ec5c7066245f090c5eb8bb7ffa6f5ac Mon Sep 17 00:00:00 2001 From: Josh Margulis Date: Tue, 7 Mar 2023 23:25:05 -0800 Subject: [PATCH 3/3] Improve horizontal scrolling for project page view --- webapp/src/components/EntityDetailsBody.tsx | 18 +- webapp/src/core/misc.ts | 11 ++ webapp/src/pages/ExternalLinkPage.tsx | 102 ++++++----- webapp/src/pages/ProjectPage.tsx | 186 ++++++++++---------- 4 files changed, 173 insertions(+), 144 deletions(-) diff --git a/webapp/src/components/EntityDetailsBody.tsx b/webapp/src/components/EntityDetailsBody.tsx index 24277a7..afa3a5e 100644 --- a/webapp/src/components/EntityDetailsBody.tsx +++ b/webapp/src/components/EntityDetailsBody.tsx @@ -30,7 +30,14 @@ import { EntityTypes } from '../core/card' import CardDetailsTitle from './EntityDetailsTitle' import CardDetailsDescription from './EntityDetailsDescription'; import CardDetailsComments from './EntityDetailsComments'; -import { CardStatus, colorToBackgroundColorClass, Colors, colorToBorderColorClass, Color } from '../core/misc'; +import { + CardStatus, + colorToBackgroundColorClass, + Colors, + colorToBorderColorClass, + Color, + copyStringToClipboard +} from '../core/misc'; import ContextMenu from './ContextMenu'; import { IFeatureComment } from '../store/featurecomments/types'; import EntityDetailsAnnotations from './EntityDetailsAnnotations'; @@ -120,14 +127,7 @@ class EntityDetailsBody extends Component { urlRef = React.createRef() copyToClipboard = (url: string) => { - const listener = (e: ClipboardEvent) => { - e.clipboardData!.setData('text/plain', url); - e.preventDefault(); - } - - document.addEventListener('copy', listener) - document.execCommand('copy'); - document.removeEventListener('copy', listener); + copyStringToClipboard(url) this.setState({ copySuccess: true }) } diff --git a/webapp/src/core/misc.ts b/webapp/src/core/misc.ts index 0b349a1..38de70a 100644 --- a/webapp/src/core/misc.ts +++ b/webapp/src/core/misc.ts @@ -17,6 +17,17 @@ export const isEditor = (level: Roles) => { return level === Roles.EDITOR || level === Roles.ADMIN || level === Roles.OWNER } +export const copyStringToClipboard = (input: string) => { + const listener = (e: ClipboardEvent) => { + e.clipboardData!.setData('text/plain', input); + e.preventDefault(); + } + + document.addEventListener('copy', listener) + document.execCommand('copy'); + document.removeEventListener('copy', listener); +} + export const daysBetween = (fromDate: Date, toDate: Date) => { const oneDay = 24 * 60 * 60 * 1000 return Math.round(Math.abs((fromDate.getTime() - toDate.getTime()) / (oneDay))); diff --git a/webapp/src/pages/ExternalLinkPage.tsx b/webapp/src/pages/ExternalLinkPage.tsx index 80d3fda..ce8b599 100644 --- a/webapp/src/pages/ExternalLinkPage.tsx +++ b/webapp/src/pages/ExternalLinkPage.tsx @@ -134,6 +134,60 @@ class ExternalLinkPage extends Component { }) } + renderHeading(project: IProject) { + return ( +
+
+
{project.title}
+
VIEW ONLY
+ {this.state.demo &&
DEMO MODE
} +
+
+
+
+
+
+ {this.state.showClosedMilestones ? +
+
+
settings
+
+
+ ) + } + + renderBoard(project: IProject) { + return ( +
+ + this.setState({ showPersonas: false })} + openPersonas={() => this.setState({ showPersonas: true })} + /> +
+ ) + } + render() { if (this.state.loading) { return (
Loading data...
) @@ -151,51 +205,9 @@ class ExternalLinkPage extends Component { -
-
-
-
{project.title}
-
VIEW ONLY
- {this.state.demo &&
DEMO MODE
} -
-
-
-
-
-
- {this.state.showClosedMilestones ? -
-
-
settings
-
-
-
- - this.setState({ showPersonas: false })} - openPersonas={() => this.setState({ showPersonas: true })} - /> -
+ { this.renderHeading(project) } +
+ { this.renderBoard(project) }
diff --git a/webapp/src/pages/ProjectPage.tsx b/webapp/src/pages/ProjectPage.tsx index dcbc6a7..9af8222 100644 --- a/webapp/src/pages/ProjectPage.tsx +++ b/webapp/src/pages/ProjectPage.tsx @@ -12,7 +12,7 @@ import { milestones, filterMilestonesOnProject } from '../store/milestones/selec import { AppState } from '../store' import { connect } from 'react-redux' import { API_GET_PROJECT, API_GET_PROJECT_RESP } from '../api'; -import { IApplication } from '../store/application/types'; +import {IApplication, IWorkspace} from '../store/application/types'; import { IMilestone } from '../store/milestones/types'; import { features, filterFeaturesOnMilestoneAndSubWorkflow } from '../store/features/selectors'; import { filterWorkflowsOnProject } from '../store/workflows/selectors'; @@ -26,7 +26,7 @@ import { loadPersonasAction } from '../store/personas/actions'; import { loadWorkflowPersonasAction } from '../store/workflowpersonas/actions'; import { loadFeatureCommentsAction } from '../store/featurecomments/actions'; import { IFeature } from '../store/features/types'; -import { isEditor, subIsInactive, subIsTrial, subIsBasicOrAbove } from '../core/misc'; +import { isEditor, subIsInactive, subIsTrial, subIsBasicOrAbove, copyStringToClipboard } from '../core/misc'; import { Button } from '../components/elements'; import queryString from 'query-string' import { featureComments, filterFeatureCommentsOnProject } from '../store/featurecomments/selectors'; @@ -182,19 +182,102 @@ class ProjectPage extends Component { copyToClipboard = (url: string) => { - const listener = (e: ClipboardEvent) => { - e.clipboardData!.setData('text/plain', url); - e.preventDefault(); - } - - document.addEventListener('copy', listener) - document.execCommand('copy'); - document.removeEventListener('copy', listener); + copyStringToClipboard(url) this.setState({ copySuccess: true }) } urlRef = React.createRef() + renderHeading(proj: IProject, viewOnly: boolean, showPrivateLink: boolean) { + return ( +
+
+
{proj.title}
+ +
+
    +
  • +
+
+
+ {viewOnly &&
VIEW ONLY
} +
+
+
+ + + {showPrivateLink && +
+ +
+
Share link
+
+ {document.queryCommandSupported('copy') && } +
+
+ check_circle +
+
+ +
+ } + +
+
+ +
+ {this.state.showClosedMilstones ? +
+ +
+
settings
+
+
+ ) + } + + renderBoard(projectId: string, viewOnly: boolean, ws: IWorkspace) { + return ( +
+ this.setState({ showPersonas: false })} + openPersonas={() => this.setState({ showPersonas: true })} + /> + + + + null} /> + + + + + + + +
+ ) + } + render() { const { projectId, workspaceName } = this.props.match.params const ws = getWorkspaceByName(this.props.application, workspaceName)! @@ -210,86 +293,9 @@ class ProjectPage extends Component { this.state.loading ?
Loading data...
: -
-
-
-
{proj.title}
- -
-
    -
  • -
-
-
- {viewOnly &&
VIEW ONLY
} -
-
-
- - - {showPrivateLink && -
- -
-
Share link
-
- {document.queryCommandSupported('copy') && } -
-
- check_circle -
-
- -
- } - -
-
- -
- {this.state.showClosedMilstones ? -
- -
-
settings
-
-
- - this.setState({ showPersonas: false })} - openPersonas={() => this.setState({ showPersonas: true })} - /> - - - - null} /> - - - - - - - +
+ { this.renderHeading(proj, viewOnly, showPrivateLink) } + { this.renderBoard(projectId, viewOnly, ws) }
:
Project not found
)