Skip to content

Commit

Permalink
File downloads UI - first take
Browse files Browse the repository at this point in the history
The info about the generated files is still pending.

See #2350
  • Loading branch information
matiasgarciaisaia committed Sep 11, 2024
1 parent 02a9384 commit ed988f8
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 112 deletions.
2 changes: 1 addition & 1 deletion assets/css/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ i {
@extend .grey-text;
font-size: 17px;
display: inline-block;
margin-left: 10px;
margin-left: 10px; // TODO: the spacing should always be placed in the container, not in the content
cursor: pointer;
span {
vertical-align: middle;
Expand Down
81 changes: 37 additions & 44 deletions assets/css/_card-modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,49 +74,11 @@
li.collection-item {
border: none;
}
li.collection-item.download {
min-height: 6rem;
}
a.download {
@extend .grey-text;
position: relative;
> div {
padding-left: 70px;
max-width: 85%;
&:first-child {
background-color: #999999;
text-align: center;
border-radius: 50%;
height: 45px;
width: 45px;
padding-left: 0;
max-width: initial;
position: absolute;
top: 4px;
left: 5px;
i.material-icons {
@extend .white-text;
font-size: 1.5rem;
line-height: 45px;
}
}
p {
font-size: 1.1rem;
margin: 0.2rem 0;
}
}
&:after {
content: "";
display: table;
clear: both;
zoom: 1;
}
.button {
background-color: color("grey", "darken-1");
}
.button[disabled] {
border: 1px rgba(0, 0, 0, 0.1) solid;
background-color: transparent;
li.collection-item .file-section {
padding-left: 70px;
p {
font-size: 1.1rem;
margin: 0.2rem 0;
}
.title {
@extend .black-text;
Expand All @@ -132,9 +94,31 @@
width: fit-content;
}
}
a.download {
display: block;
text-align: center;
height: 45px;
width: 45px;
padding-left: 0;
max-width: initial;
i.material-icons {
@extend .black-text;
font-size: 1.5rem;
}
position: absolute;
top: 4px;
left: 5px;
&:after {
content: "";
display: table;
clear: both;
zoom: 1;
}
}
.access-link {
padding: 0.5rem 0;
max-width: 85%;
display: flex;
align-items: center;
.switch {
display: inline-block;
vertical-align: middle;
Expand Down Expand Up @@ -179,6 +163,15 @@
}
}
}
.file-download {
display: flex;
align-items: center;
gap: 0.5rem;

.btn-icon-grey {
margin-left: initial;
}
}
div.link {
@extend .grey-text;
> div {
Expand Down
127 changes: 63 additions & 64 deletions assets/js/components/respondents/RespondentIndex.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type Props = {
}

type State = {
csvType: string,
shownFile: string,
}

class RespondentIndex extends Component<Props, State> {
Expand All @@ -74,7 +74,7 @@ class RespondentIndex extends Component<Props, State> {

constructor(props) {
super(props)
this.state = { csvType: "" }
this.state = { shownFile: null }
this.toggleResultsLink = this.toggleResultsLink.bind(this)
this.toggleIncentivesLink = this.toggleIncentivesLink.bind(this)
this.toggleInteractionsLink = this.toggleInteractionsLink.bind(this)
Expand Down Expand Up @@ -249,7 +249,7 @@ class RespondentIndex extends Component<Props, State> {
<label>
<input type="checkbox" checked={link != null} onChange={() => onChange(link)} />
<span className="lever" />
<span className="label">{t("Public link:")}</span>
<span className="label">{t("Public link")}{link == null ? "" : ":"}</span>
</label>
</div>
) : (
Expand All @@ -260,7 +260,7 @@ class RespondentIndex extends Component<Props, State> {
<span ref={name}>{link.url}</span>
<div className="buttons">
{!project.readOnly ? (
<Tooltip text="Refresh">
<Tooltip text="Regenerate link">
<a className="btn-icon-grey" onClick={refresh}>
<i className="material-icons">refresh</i>
</a>
Expand Down Expand Up @@ -317,8 +317,15 @@ class RespondentIndex extends Component<Props, State> {
return numericFields.some((field) => field == filterField)
}

downloadItem(id, itemType) {
toggleFile(fileId, event) {
event.preventDefault()
this.setState({ shownFile: this.state.shownFile == fileId ? null : fileId })
}

downloadItem(id) {
const { t, totalCount, filter } = this.props
const { shownFile } = this.state
const currentFile = shownFile == id
let item: ?{
title: String,
description: String,
Expand Down Expand Up @@ -407,41 +414,52 @@ class RespondentIndex extends Component<Props, State> {
return null
} else {
const disabled = item.disabled
const titleDescription = (
<div>
<p disabled={disabled} className="title">
<b>{item.title}</b>
</p>
<p>{item.description}</p>
{disabled ? <p className="disabled-clarification">{item.disabledText}</p> : null}

const downloadButton = (
<div className="file-download">
<Tooltip text={t("Download file")}>
<a className="black-text">
<i className="material-icons">get_app</i>
</a>
</Tooltip>
<span className="">{t("Download last generated file")}</span>
<span className="grey-text">
{ // (15 min ago
// FIXME: this should be calculated
}
<Tooltip text={t("Regenerate file")}>
<a className="btn-icon-grey">
<i className="material-icons">refresh</i>
</a>
</Tooltip>
{ // )
}
</span>
</div>
)

return (
<li disabled={disabled} className="collection-item">
{itemType == "file" ? (
<a
href="#"
className="download"
onClick={(e) => {
if (disabled) return
e.preventDefault()
item && item.onDownload()
}}
>
<div disabled={disabled} className="button">
{disabled ? (
<div disabled={disabled} className="file-download-off-icon" />
) : (
<i className="material-icons">get_app</i>
)}
<div style={{position: 'relative'}}>
<a href="#!" className="download" onClick={(e) => this.toggleFile(id, e)}>
<div disabled={disabled} className="button">
<i className="material-icons">{currentFile ? "expand_more" : "chevron_right"}</i>
</div>
</a>
<div className="file-section">
<p disabled={disabled} className="title">
<b>{item.title}</b>
</p>
<p>{item.description}</p>
{disabled ? <p className="disabled-clarification">{item.disabledText}</p> : null}
{ currentFile ?
<div className="download-section">
{ item.downloadLink }
{ downloadButton }
</div>
{titleDescription}
</a>
) : (
<div className="link">{titleDescription}</div>
)}
{itemType == "link" ? item.downloadLink : null}
: ""
}
</div></div>
</li>
)
}
Expand All @@ -458,29 +476,22 @@ class RespondentIndex extends Component<Props, State> {
return <RespondentsFilter defaultValue={q} onChange={(value) => this.onFilterChange(value)} />
}

downloadModal({ itemType }) {
downloadModal() {
const { userLevel, t, filter } = this.props
const ownerOrAdmin = userLevel == "owner" || userLevel == "admin"
const [title, description] =
itemType == "file"
? [t("Download CSV"), t("Choose the data you want to download")]
: [
t("Public links"),
t("Choose the data you want to be able to access through a public link"),
]

return (
<Modal id={`downloadCSV-${itemType}`} confirmationText="Download CSV" card>
<Modal id={`downloadCSV`} confirmationText="Download CSV" card>
<div className="card-title header">
<h5>{title}</h5>
<p>{description}</p>
<h5>{t("Download CSV")}</h5>
<p>{t("Choose the data you want to download")}</p>
</div>
<ul className="collection repondents-index-modal">
{itemType == "file" && filter ? this.downloadItem("filtered-results", itemType) : null}
{this.downloadItem("results", itemType)}
{this.downloadItem("disposition-history", itemType)}
{ownerOrAdmin ? this.downloadItem("incentives", itemType) : null}
{ownerOrAdmin ? this.downloadItem("interactions", itemType) : null}
{filter ? this.downloadItem("filtered-results") : null}
{this.downloadItem("results")}
{this.downloadItem("disposition-history")}
{ownerOrAdmin ? this.downloadItem("incentives") : null}
{ownerOrAdmin ? this.downloadItem("interactions") : null}
</ul>
</Modal>
)
Expand Down Expand Up @@ -676,20 +687,8 @@ class RespondentIndex extends Component<Props, State> {
__html: "<style> body { overflow-y: auto !important; color: black}</style>",
}}
/>
<MainAction text="Downloads" icon="get_app">
<Action
text="Download CSVs"
icon="insert_drive_file"
onClick={() => $(`#downloadCSV-${fileId}`).modal("open")}
/>
<Action
text="Public links"
icon="link"
onClick={() => $(`#downloadCSV-${linkId}`).modal("open")}
/>
</MainAction>
{this.downloadModal({ itemType: fileId })}
{this.downloadModal({ itemType: linkId })}
<MainAction text="Downloads" icon="get_app" onClick={() => $('#downloadCSV').modal("open")}/>
{this.downloadModal()}
{this.renderColumnPickerModal()}
{this.respondentsFilter()}
<CardTable
Expand Down
7 changes: 4 additions & 3 deletions locales/template/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
"Channels <1><0>{{ names }}</0></1> down<3>{\" \"}</3> <5></5>": "Channels <1><0>{{ names }}</0></1> down<3>{\" \"}</3> <5></5>",
"Checking this box will make the survey accept written numbers as valid numeric responses, like \"one\" or \"fifty five\". Written numbers are supported up to one hundred (100).": "",
"Choose a key for each language": "",
"Choose the data you want to be able to access through a public link": "",
"Choose the data you want to download": "",
"Choose the disposition you want to set at this point of the questionnaire.": "",
"Choose the questionnaire answers you want to use to define quotas": "",
Expand Down Expand Up @@ -144,6 +143,8 @@
"Done": "",
"Download CSV": "",
"Download contents as CSV": "",
"Download file": "",
"Download last generated file": "",
"Downloaded <i>{{surveyName}}</i> {{reportType}}": "",
"Drop your CSV file here, or click to browse": "",
"Drop your MP3, WAV, M4A, ACC or MP4 file here, or click to browse": "",
Expand Down Expand Up @@ -344,8 +345,7 @@
"Project successfully unarchived": "",
"Projects": "",
"Provider": "",
"Public link:": "",
"Public links": "",
"Public link": "",
"QUEUE SIZE": "",
"Quantity": "",
"Question Prompt": "",
Expand All @@ -372,6 +372,7 @@
"Ready to launch_survey": "",
"Record": "",
"Refused": "",
"Regenerate file": "",
"Registered": "",
"Rejected": "",
"Remove collaborator": "",
Expand Down

0 comments on commit ed988f8

Please sign in to comment.