Skip to content

Commit

Permalink
Merge pull request #1568 from pierotofy/pubedit
Browse files Browse the repository at this point in the history
Public edits
  • Loading branch information
pierotofy authored Nov 6, 2024
2 parents eaf0db9 + f1e6b3a commit 46ea00b
Show file tree
Hide file tree
Showing 13 changed files with 210 additions and 105 deletions.
6 changes: 4 additions & 2 deletions app/api/potree.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ def post(self, request, pk=None, project_pk=None):
"""
Store potree scene information (except camera view)
"""
get_and_check_project(request, project_pk, perms=("change_project", ))
task = self.get_and_check_task(request, pk)
if (not task.public) or (task.public and not task.public_edit):
get_and_check_project(request, project_pk, perms=("change_project", ))
scene = request.data

# Quick type check
Expand All @@ -36,8 +37,9 @@ def post(self, request, pk=None, project_pk=None):
"""
Store camera view information
"""
get_and_check_project(request, project_pk, perms=("change_project", ))
task = self.get_and_check_task(request, pk)
if (not task.public) or (task.public and not task.public_edit):
get_and_check_project(request, project_pk, perms=("change_project", ))

view = request.data
if not view:
Expand Down
25 changes: 25 additions & 0 deletions app/migrations/0040_auto_20241106_1832.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 2.2.27 on 2024-11-06 18:32

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('app', '0039_task_orthophoto_bands'),
]

operations = [
migrations.AddField(
model_name='task',
name='public_edit',
field=models.BooleanField(default=False, help_text='A flag indicating whether this public task can be edited', verbose_name='Public Edit'),
),
migrations.AlterField(
model_name='plugindatum',
name='user',
field=models.ForeignKey(blank=True, default=None, help_text='The user this setting belongs to. If NULL, the setting is global.', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User'),
),
]
4 changes: 4 additions & 0 deletions app/models/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ class Task(models.Model):
pending_action = models.IntegerField(choices=PENDING_ACTIONS, db_index=True, null=True, blank=True, help_text=_("A requested action to be performed on the task. The selected action will be performed by the worker at the next iteration."), verbose_name=_("Pending Action"))

public = models.BooleanField(default=False, help_text=_("A flag indicating whether this task is available to the public"), verbose_name=_("Public"))
public_edit = models.BooleanField(default=False, help_text=_("A flag indicating whether this public task can be edited"), verbose_name=_("Public Edit"))

resize_to = models.IntegerField(default=-1, help_text=_("When set to a value different than -1, indicates that the images for this task have been / will be resized to the size specified here before processing."), verbose_name=_("Resize To"))

upload_progress = models.FloatField(default=0.0,
Expand Down Expand Up @@ -1007,6 +1009,7 @@ def get_map_items(self):
'name': self.name,
'project': self.project.id,
'public': self.public,
'public_edit': self.public_edit,
'camera_shots': camera_shots,
'ground_control_points': ground_control_points,
'epsg': self.epsg,
Expand All @@ -1024,6 +1027,7 @@ def get_model_display_params(self):
'project': self.project.id,
'available_assets': self.available_assets,
'public': self.public,
'public_edit': self.public_edit,
'epsg': self.epsg
}

Expand Down
3 changes: 3 additions & 0 deletions app/static/app/js/MapView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class MapView extends React.Component {
selectedMapType: 'auto',
title: "",
public: false,
publicEdit: false,
shareButtons: true,
permissions: ["view"]
};
Expand All @@ -20,6 +21,7 @@ class MapView extends React.Component {
selectedMapType: PropTypes.oneOf(['auto', 'orthophoto', 'plant', 'dsm', 'dtm']),
title: PropTypes.string,
public: PropTypes.bool,
publicEdit: PropTypes.bool,
shareButtons: PropTypes.bool,
permissions: PropTypes.array
};
Expand Down Expand Up @@ -152,6 +154,7 @@ class MapView extends React.Component {
showBackground={true}
mapType={this.state.selectedMapType}
public={this.props.public}
publicEdit={this.props.publicEdit}
shareButtons={this.props.shareButtons}
permissions={this.props.permissions}
thermal={isThermal}
Expand Down
2 changes: 2 additions & 0 deletions app/static/app/js/components/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Map extends React.Component {
showBackground: false,
mapType: "orthophoto",
public: false,
publicEdit: false,
shareButtons: true,
permissions: ["view"],
thermal: false
Expand All @@ -45,6 +46,7 @@ class Map extends React.Component {
tiles: PropTypes.array.isRequired,
mapType: PropTypes.oneOf(['orthophoto', 'plant', 'dsm', 'dtm']),
public: PropTypes.bool,
publicEdit: PropTypes.bool,
shareButtons: PropTypes.bool,
permissions: PropTypes.array,
thermal: PropTypes.bool
Expand Down
86 changes: 65 additions & 21 deletions app/static/app/js/components/SharePopup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class SharePopup extends React.Component{
this.state = {
task: props.task,
togglingShare: false,
togglingEdits: false,
error: "",
showQR: false,
linkControls: [], // coming from plugins,
Expand Down Expand Up @@ -63,6 +64,7 @@ class SharePopup extends React.Component{
}

handleEnableSharing(e){
if (e) e.preventDefault();
const { task } = this.state;

this.setState({togglingShare: true});
Expand All @@ -86,6 +88,31 @@ class SharePopup extends React.Component{
});
}

handleAllowEdits = e => {
e.preventDefault();
const { task } = this.state;

this.setState({togglingEdits: true});

return $.ajax({
url: `/api/projects/${task.project}/tasks/${task.id}/`,
contentType: 'application/json',
data: JSON.stringify({
public_edit: !this.state.task.public_edit
}),
dataType: 'json',
type: 'PATCH'
})
.done((task) => {
this.setState({task});
this.props.taskChanged(task);
})
.fail(() => this.setState({error: _("An error occurred. Check your connection and permissions.")}))
.always(() => {
this.setState({togglingEdits: false});
});
}

toggleQRCode = () => {
this.setState({showQR: !this.state.showQR});
}
Expand All @@ -98,30 +125,47 @@ class SharePopup extends React.Component{
return (<div onMouseDown={e => { e.stopPropagation(); }} className={"sharePopup " + this.props.placement}>
<div className={"sharePopupContainer popover in " + this.props.placement}>
<div className="arrow"></div>
<h3 className="popover-title theme-background-highlight">{_("Share This Task")}</h3>
<div className="popover-content theme-secondary">
<ErrorMessage bind={[this, 'error']} />
<div className="checkbox">
<button type="button"
<h3 className="popover-title theme-background-highlight">{_("Share This Task")}
<button type="button" title={_("QR")}
className={"btn btn-qrcode btn-sm " +
(this.state.showQR ? "btn-primary " : "btn-default ") +
(!this.state.task.public ? "hide" : "")}
onClick={this.toggleQRCode}>
<i className="fa fa-qrcode"></i> {_("QR")}
<i className="fa fa-qrcode"></i>
</button>

<label onClick={this.handleEnableSharing}>
{this.state.togglingShare ?
<i className="fa fa-sync fa-spin fa-fw"></i>
: ""}

<input
className={this.state.togglingShare ? "hide" : ""}
type="checkbox"
checked={this.state.task.public}
onChange={() => {}}
/> {_("Enabled")}
</label>
</h3>
<div className="popover-content theme-secondary">
<ErrorMessage bind={[this, 'error']} />

<div className="checkboxes">
<div className="checkbox">
<label onClick={this.handleEnableSharing}>
{this.state.togglingShare ?
<i className="fa fa-sync fa-spin fa-fw"></i>
: ""}

<input
className={this.state.togglingShare ? "hide" : ""}
type="checkbox"
checked={this.state.task.public}
onChange={() => {}}
/> {_("Enabled")}
</label>
</div>
{this.state.task.public ? <div className="checkbox last">
<label onClick={this.handleAllowEdits}>
{this.state.togglingEdits ?
<i className="fa fa-sync fa-spin fa-fw"></i>
: ""}

<input
className={this.state.togglingEdits ? "hide" : ""}
type="checkbox"
checked={this.state.task.public_edit}
onChange={() => {}}
/> {_("Allow Edits")}
</label>
</div> : ""}
</div>
<div className={"share-links " + (this.state.task.public ? "show" : "")}>
<div className={"form-group " + (this.state.showQR ? "hide" : "")}>
Expand Down Expand Up @@ -152,10 +196,10 @@ class SharePopup extends React.Component{
/>
</label>
</div>
<div className={(this.state.showQR ? "" : "hide")}>
<div className={(this.state.showQR ? "" : "hide") + " text-center"}>
<QRCode
value={shareLink}
size={200}
size={164}
bgColor={"#ffffff"}
fgColor={"#000000"}
level={"M"}
Expand Down
20 changes: 14 additions & 6 deletions app/static/app/js/css/SharePopup.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,31 @@

h3.popover-title{
padding-top: 8px;
display: flex;
justify-content: space-between;
}

.checkboxes{
display: flex;
justify-content: space-between;
}

.btn-qr{
max-height: 32px;
}

.checkbox{
margin-top: 0;
&.last{
margin-left: 12px;
}
}

.fa-sync{
margin-left: -25px;
margin-right: 5px;
}

.btn-qrcode{
position: absolute;
right: 0px;
top: -6px;
}

.share-links{
& > div{
margin-top: 8px;
Expand Down
Loading

0 comments on commit 46ea00b

Please sign in to comment.