mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-09-12 21:58:57 +02:00
"Report an issue" in the navbar read like a way to report an anonymized
repository, and it opened a blank GitHub issue instead of the template
that asks reporters to confirm the issue is about the service. The user
menu offered "Default settings" and "Logout" with no hint of what lives
behind them, and the Claim page was unreachable from any menu.
The settings page never loaded quotas (the bars stayed in their striped
loading state), mixed serif checkbox labels with sans forms, used
Bootstrap alert colours, and described options in jargon ("Proxy mode",
"Github page", "Line of code").
- Navbar: "Report a bug" links to the issue template with a tooltip that
names the service; the user menu shows who is signed in and lists
Settings, Claim an anonymization, Report a bug, Source code, Sign out,
each with a one-line hint. Icon links get aria-labels.
- Settings: quotas load through a shared quotaService (also used by the
dashboard); sections match the side navigation, which now follows
scrolling via a small paperScrollspy directive; copy explains each
option; account card with Sign out; delete moved into a danger zone;
Save shows Saving/Saved and the error alert uses the paper palette.
- Conferences list and detail: sort and status buttons show their state,
hidden statuses appear as chips with a count line, Remove is a button
behind a divider, dates spell the month, expiry column matches the
dashboard, detail page gets an Edit button and plan/cost meta.
- New conference: validation errors only appear after a field is touched
or the form submitted; pricing copy matches how price is computed.
- Status page: progress label no longer overlaps the details below it;
"Report a bug" points at the template and says whom it is for.
- Claim: single rule, constrained width, explains when to use it.
- Anonymize: shorter placeholder, consistent Auto-update label.
- Mock server gains the endpoints these pages need and an ANON mode.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
199 lines
11 KiB
HTML
199 lines
11 KiB
HTML
<div class="container paper-page paper-settings">
|
|
<div class="paper-crumbs"><a href="/dashboard">My work</a> / <span class="here">Settings</span></div>
|
|
<h1 class="paper-page-title">Your <em>settings</em></h1>
|
|
<p class="paper-page-lede">Defaults applied to every new anonymization, your quotas, and your account.</p>
|
|
|
|
<div class="paper-settings-body">
|
|
<aside class="paper-settings-toc" paper-scrollspy>
|
|
<div class="paper-settings-toc-head">On this page</div>
|
|
<nav>
|
|
<a href="#settings-quota">Quota</a>
|
|
<a href="#settings-terms">Terms to redact</a>
|
|
<a href="#settings-display">Display</a>
|
|
<a href="#settings-features">Features</a>
|
|
<a href="#settings-expiration">Expiration</a>
|
|
<a href="#settings-account">Account</a>
|
|
</nav>
|
|
</aside>
|
|
|
|
<div class="paper-settings-main">
|
|
<!-- Quota: same markup as the dashboard, driven by quotaService -->
|
|
<section id="settings-quota" class="paper-settings-section">
|
|
<div class="paper-section-eyebrow">Quota</div>
|
|
<p class="paper-section-copy">What you are using across all your anonymizations. Conferences can lift these limits during a review window.</p>
|
|
<div class="quota-row" ng-if="quota">
|
|
<div class="quota-item" ng-repeat="q in [
|
|
{key: 'repository', label: 'Repositories', kind: 'count'},
|
|
{key: 'storage', label: 'Storage', kind: 'bytes'},
|
|
{key: 'file', label: 'Files', kind: 'count'}
|
|
]">
|
|
<div class="quota-header">
|
|
<span class="quota-label">{{q.label}}</span>
|
|
<span class="quota-value" ng-if="q.kind === 'count'">
|
|
{{quota[q.key].used | number}}<span ng-if="!quota[q.key].unlimited"> / {{quota[q.key].total | number}}</span>
|
|
<span class="quota-unlimited-tag" ng-if="quota[q.key].unlimited">Unlimited</span>
|
|
</span>
|
|
<span class="quota-value" ng-if="q.kind === 'bytes'">
|
|
{{quota[q.key].used | humanFileSize}}<span ng-if="!quota[q.key].unlimited"> / {{quota[q.key].total | humanFileSize}}</span>
|
|
<span class="quota-unlimited-tag" ng-if="quota[q.key].unlimited">Unlimited</span>
|
|
</span>
|
|
</div>
|
|
<div
|
|
class="quota-track"
|
|
ng-class="'quota-' + quota[q.key].level"
|
|
role="progressbar"
|
|
aria-label="{{q.label}} quota"
|
|
aria-valuenow="{{quota[q.key].used}}"
|
|
aria-valuemin="0"
|
|
aria-valuemax="{{quota[q.key].unlimited ? quota[q.key].used : quota[q.key].total}}"
|
|
aria-valuetext="{{quota[q.key].unlimited ? 'unlimited' : (quota[q.key].percent | number:0) + '% used'}}"
|
|
>
|
|
<div class="quota-fill" ng-if="!quota[q.key].unlimited" ng-style="{width: quota[q.key].percent + '%'}"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="quota-row" ng-if="!quota" aria-hidden="true">
|
|
<div class="quota-item" ng-repeat="i in [1, 2, 3]">
|
|
<div class="quota-header"><span class="skeleton skeleton-line" style="width: 40%"></span><span class="skeleton skeleton-line" style="width: 25%"></span></div>
|
|
<div class="quota-track"></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<form class="form needs-validation" name="defaultsForm" novalidate ng-submit="saveDefault($event)">
|
|
<section id="settings-terms" class="paper-settings-section">
|
|
<div class="paper-section-eyebrow">Terms to redact</div>
|
|
<p class="paper-section-copy">Pre-filled in every new anonymization. You can still edit the list per anonymization.</p>
|
|
<div class="form-group">
|
|
<label class="paper-field-label" for="terms">Default terms</label>
|
|
<textarea
|
|
class="form-control"
|
|
id="terms"
|
|
name="terms"
|
|
rows="4"
|
|
placeholder="Jane Smith MIT CSAIL jane.smith@example.org"
|
|
ng-model="terms"
|
|
ng-model-options="{ debounce: 250 }"
|
|
></textarea>
|
|
<small id="termsHelp" class="form-text text-muted">
|
|
One term per line (regex allowed). Each match is replaced by
|
|
<code>{{site_options.ANONYMIZATION_MASK || 'XXX'}}-[N]</code>, or use <code>term=>replacement</code> to pick your own.
|
|
</small>
|
|
<div class="invalid-feedback" ng-show="defaultsForm.terms.$error.format">
|
|
Terms are in an invalid format
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="settings-display" class="paper-settings-section">
|
|
<div class="paper-section-eyebrow">Display</div>
|
|
<p class="paper-section-copy">What reviewers can see inside an anonymized repository.</p>
|
|
<div class="form-group paper-check-list">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="link" name="link" ng-model="options.link" />
|
|
<label class="form-check-label" for="link">Keep links</label>
|
|
<small class="form-text text-muted">Unchecked, every link in text files is removed.</small>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="image" name="image" ng-model="options.image" />
|
|
<label class="form-check-label" for="image">Display images</label>
|
|
<small class="form-text text-muted">Images are shown as is. They are not anonymized.</small>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="pdf" name="pdf" ng-model="options.pdf" />
|
|
<label class="form-check-label" for="pdf">Display PDFs</label>
|
|
<small class="form-text text-muted">PDFs are shown as is. They are not anonymized.</small>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="notebook" name="notebook" ng-model="options.notebook" />
|
|
<label class="form-check-label" for="notebook">Display notebooks</label>
|
|
<small class="form-text text-muted">Render Jupyter notebooks instead of raw JSON.</small>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="settings-features" class="paper-settings-section">
|
|
<div class="paper-section-eyebrow">Features</div>
|
|
<div class="form-group paper-check-list">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="page" name="page" ng-model="options.page" />
|
|
<label class="form-check-label" for="page">GitHub Pages</label>
|
|
<small class="form-text text-muted">Serve an anonymized copy of the repository's GitHub Pages site. Only pages built from the anonymized branch are supported.</small>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="loc" name="loc" ng-model="options.loc" />
|
|
<label class="form-check-label" for="loc">Lines of code</label>
|
|
<small class="form-text text-muted">Show the line count of the repository in the explorer.</small>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="update" name="update" ng-model="options.update" />
|
|
<label class="form-check-label" for="update">Auto-update from GitHub</label>
|
|
<small class="form-text text-muted">Follow the branch and pull the latest commit automatically, at most once an hour.</small>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="paper-field-label" for="mode">Fetch mode</label>
|
|
<select class="form-control" id="mode" name="mode" ng-model="options.mode">
|
|
<option value="GitHubStream" selected>Stream from GitHub on demand</option>
|
|
<option value="GitHubDownload">Download to Anonymous GitHub</option>
|
|
</select>
|
|
<small class="form-text text-muted">
|
|
Download is faster for reviewers and enables every feature. Streaming is the only option above
|
|
{{site_options.MAX_REPO_SIZE * 1024 | humanFileSize}}.
|
|
</small>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="settings-expiration" class="paper-settings-section">
|
|
<div class="paper-section-eyebrow">Expiration</div>
|
|
<div class="form-group">
|
|
<label class="paper-field-label" for="expiration">When an anonymization expires</label>
|
|
<select class="form-control" id="expiration" name="expiration" ng-model="options.expirationMode">
|
|
<option value="redirect">Redirect visitors to the GitHub repository</option>
|
|
<option value="remove" selected>Remove the anonymized repository</option>
|
|
</select>
|
|
<small class="form-text text-muted">
|
|
The expiration date itself is chosen per anonymization. Redirecting reveals the source repository, so pick it only once the review is over.
|
|
</small>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="paper-settings-footer">
|
|
<div class="paper-inline-alert paper-inline-alert-error" role="alert" ng-if="error"><i class="fas fa-exclamation-circle" aria-hidden="true"></i> <span ng-bind="error"></span></div>
|
|
<div class="paper-settings-actions">
|
|
<button id="save" type="submit" class="btn btn-ink" ng-disabled="saving">
|
|
<i class="fas fa-check mr-1" aria-hidden="true" ng-if="message"></i>{{ saving ? 'Saving…' : (message ? 'Saved' : 'Save defaults') }}
|
|
</button>
|
|
<span class="paper-settings-hint">Applies to new anonymizations only. Existing ones keep their settings.</span>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<section id="settings-account" class="paper-settings-section">
|
|
<div class="paper-section-eyebrow">Account</div>
|
|
<div class="paper-account-card">
|
|
<img ng-src="{{user.photo}}" ng-if="user.photo" width="40" height="40" class="rounded-circle" alt="" />
|
|
<div class="paper-account-identity">
|
|
<div class="paper-account-name">@{{user.username}}</div>
|
|
<div class="paper-account-meta">Signed in with GitHub. Anonymous GitHub only reads your repositories.</div>
|
|
</div>
|
|
<a class="btn btn-outline-ink" href="/api/user/logout" target="_self">Sign out</a>
|
|
</div>
|
|
|
|
<div class="paper-danger-zone">
|
|
<div class="paper-danger-head">Delete account</div>
|
|
<p class="paper-danger-copy">
|
|
Removes all your anonymized repositories, gists, and pull requests,
|
|
revokes the application's access to your GitHub account, and erases
|
|
your personal data (username, email, access tokens). This cannot be undone.
|
|
</p>
|
|
<div class="paper-inline-alert paper-inline-alert-error" role="alert" ng-if="deleteError"><i class="fas fa-exclamation-circle" aria-hidden="true"></i> <span ng-bind="deleteError"></span></div>
|
|
<button type="button" class="btn btn-outline-danger" ng-click="deleteAccount()" ng-disabled="deletingAccount">
|
|
<i class="fas fa-trash-alt mr-1" aria-hidden="true"></i>{{ deletingAccount ? 'Deleting…' : 'Delete my account' }}
|
|
</button>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</div>
|