Skip to content

Commit

Permalink
Merge pull request #159 from dekart-xyz/allow-edit-reports
Browse files Browse the repository at this point in the history
Allow edit reports
  • Loading branch information
delfrrr authored Feb 2, 2024
2 parents cb4c21a + 8430f56 commit 1c0a05f
Show file tree
Hide file tree
Showing 16 changed files with 622 additions and 441 deletions.
1 change: 1 addition & 0 deletions migrations/000017_reports_editable.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE reports ADD COLUMN allow_edit boolean default false;
11 changes: 7 additions & 4 deletions proto/dekart.proto
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ message GetUsageResponse {

message SetDiscoverableRequest {
string report_id = 1;
bool discoverable = 2;
bool discoverable = 2; // report is discoverable by other users of the same instance
bool allow_edit = 3; // allow other users to edit the report
}

message SetDiscoverableResponse {
Expand Down Expand Up @@ -216,8 +217,10 @@ message Report {
bool can_write = 5;
string author_email = 6;
bool discoverable = 7; // report is discoverable by other users of the same instance
int64 created_at = 8;
int64 updated_at = 9;
bool allow_edit = 8; // allow other users to edit the report
bool is_author = 9; // user is the author of the report
int64 created_at = 10;
int64 updated_at = 11;
}

message Dataset {
Expand Down Expand Up @@ -283,7 +286,7 @@ message File {
}

message UpdateReportRequest {
Report report = 1;
Report report = 1; // MapConfig, Title, Id will be used for update
repeated Query query = 2;
}

Expand Down
4 changes: 2 additions & 2 deletions src/client/ReportHeaderButtons.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function RefreshButton () {
function EditModeButtons ({ changed }) {
const dispatch = useDispatch()
const history = useHistory()
const { id, discoverable, canWrite } = useSelector(state => state.report)
const { id, discoverable, canWrite, allowEdit, isAuthor } = useSelector(state => state.report)
const { canSave } = useSelector(state => state.reportStatus)

return (
Expand All @@ -92,7 +92,7 @@ function EditModeButtons ({ changed }) {
title='Present Mode'
onClick={() => history.replace(`/reports/${id}`)}
/>
<ShareButton reportId={id} discoverable={discoverable} canWrite={canWrite} />
<ShareButton reportId={id} discoverable={discoverable} isAuthor={isAuthor} allowEdit={allowEdit} />
{canWrite
? (
<>
Expand Down
83 changes: 59 additions & 24 deletions src/client/ShareButton.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Button from 'antd/es/button'
import Modal from 'antd/es/modal'
import { ExportOutlined, UsergroupAddOutlined, LinkOutlined, LockOutlined, InfoCircleOutlined, FileSearchOutlined } from '@ant-design/icons'
import { useState } from 'react'
import { EditOutlined, ExportOutlined, UsergroupAddOutlined, LinkOutlined, LockOutlined, InfoCircleOutlined, FileSearchOutlined } from '@ant-design/icons'
import { useEffect, useState } from 'react'
import styles from './ShareButton.module.css'
import { useDispatch, useSelector } from 'react-redux'
import Tooltip from 'antd/es/tooltip'
Expand Down Expand Up @@ -41,12 +41,21 @@ function AuthTypeTitle ({ authType, referer }) {
)
}

function ModalContent ({ reportId, discoverable, canWrite }) {
function ModalContent ({ reportId, discoverable, isAuthor, allowEdit }) {
const env = useSelector(state => state.env)
const usage = useSelector(state => state.usage)
const { loaded: envLoaded, authEnabled, authType } = env
const dispatch = useDispatch()
const [discoverableSwitch, setDiscoverableSwitch] = useState(discoverable)
const [allowEditSwitch, setAllowEditSwitch] = useState(allowEdit)

// when changed by another user, reset state
useEffect(() => {
setDiscoverableSwitch(discoverable)
}, [discoverable])
useEffect(() => {
setAllowEditSwitch(allowEdit)
}, [allowEdit])

if (!envLoaded) {
return null
Expand All @@ -58,32 +67,58 @@ function ModalContent ({ reportId, discoverable, canWrite }) {
<div className={styles.reportStatus}>
<div className={styles.reportStatusIcon}><LockOutlined /></div>
<div className={styles.reportStatusDetails}>
<div className={styles.reportStatusDetailsText}> Everyone with a link can view this report</div>
<div className={styles.reportStatusDetailsText}>{(() => {
switch (true) {
case discoverable && allowEdit:
return 'Everyone can view and edit report'
case !discoverable && allowEdit:
return 'Everyone with link can edit report'
case discoverable && !allowEdit:
return 'Everyone with link can view and refresh report'
default:
return 'Everyone with a link can view report'
}
})()}
</div>
<div className={styles.reportAuthStatus}>
<Tooltip title={<AuthTypeTitle authType={authType} referer={getRef(env, usage)} />}>
<span className={styles.authEnabled}>User authorization enabled</span>
</Tooltip>
</div>
</div>
</div>
{canWrite
? (
<div className={styles.discoverableStatus}>
<div className={styles.discoverableStatusIcon}><FileSearchOutlined /></div>
<div className={styles.discoverableStatusLabel}>Allow everyone to discover and refresh report</div>
<div className={styles.discoverableStatusControl}>
<Switch
checked={discoverable}
onChange={(checked) => {
setDiscoverableSwitch(checked)
dispatch(setDiscoverable(reportId, checked))
}}
loading={discoverableSwitch !== discoverable}
/>
</div>
</div>
)
: null}
<div className={styles.boolStatus}>
<div className={styles.boolStatusIcon}><FileSearchOutlined /></div>
<div className={styles.boolStatusLabel}>Allow everyone to discover and refresh report</div>
<div className={styles.boolStatusControl}>
<Switch
checked={discoverable}
disabled={!isAuthor}
title={!isAuthor ? 'Only the author can change this setting' : undefined}
onChange={(checked) => {
setDiscoverableSwitch(checked)
dispatch(setDiscoverable(reportId, checked, allowEdit))
}}
loading={discoverableSwitch !== discoverable}
/>
</div>
</div>
<div className={styles.boolStatus}>
<div className={styles.boolStatusIcon}><EditOutlined /></div>
<div className={styles.boolStatusLabel}>Allow everyone to edit the report</div>
<div className={styles.boolStatusControl}>
<Switch
checked={allowEdit}
disabled={!isAuthor}
title={!isAuthor ? 'Only the author can change this setting' : undefined}
onChange={(checked) => {
setAllowEditSwitch(checked)
dispatch(setDiscoverable(reportId, discoverable, checked))
}}
loading={allowEditSwitch !== allowEdit}
/>
</div>
</div>
</>
)
}
Expand Down Expand Up @@ -133,7 +168,7 @@ function ExportDropdown ({ setModalOpen }) {
)
}

export default function ShareButton ({ reportId, discoverable, canWrite }) {
export default function ShareButton ({ reportId, discoverable, isAuthor, allowEdit }) {
const [modalOpen, setModalOpen] = useState(false)
return (
<>
Expand Down Expand Up @@ -162,7 +197,7 @@ export default function ShareButton ({ reportId, discoverable, canWrite }) {
</div>
}
>
<ModalContent reportId={reportId} discoverable={discoverable} canWrite={canWrite} />
<ModalContent reportId={reportId} discoverable={discoverable} isAuthor={isAuthor} allowEdit={allowEdit} />
</Modal>
</>
)
Expand Down
7 changes: 4 additions & 3 deletions src/client/ShareButton.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
flex: 1;
}

.discoverableStatusIcon {
.boolStatusIcon {
font-size: 1.2em;
position: relative;
opacity: 0.65;
Expand All @@ -29,7 +29,8 @@
margin-left: 10px;
}

.discoverableStatusLabel {
.boolStatusLabel {
flex: 1;
font-size: 1.2em;
margin-left: 10px;
margin-right: 10px;
Expand All @@ -39,7 +40,7 @@
font-size: 1.2em;
}

.discoverableStatus {
.boolStatus {
border-top: 1px solid #f0f0f0;
padding: 20px;
display: flex;
Expand Down
3 changes: 2 additions & 1 deletion src/client/actions/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,13 @@ export function reportsListUpdate (reportsList) {
return { type: reportsListUpdate.name, reportsList }
}

export function setDiscoverable (reportId, discoverable) {
export function setDiscoverable (reportId, discoverable, allowEdit) {
return async (dispatch) => {
dispatch({ type: setDiscoverable.name })
const req = new SetDiscoverableRequest()
req.setReportId(reportId)
req.setDiscoverable(discoverable)
req.setAllowEdit(allowEdit)
dispatch(grpcCall(Dekart.SetDiscoverable, req))
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/client/reducers/rootReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ function reportsList (state = defaultReportsList, action) {
return {
...state,
loaded: true,
my: action.reportsList.filter(report => !report.archived && report.canWrite),
my: action.reportsList.filter(report => !report.archived && report.isAuthor),
archived: action.reportsList.filter(report => report.archived),
discoverable: action.reportsList.filter(report => report.discoverable && !report.archived)
}
Expand Down
Loading

0 comments on commit 1c0a05f

Please sign in to comment.