mirror of
https://github.com/overleaf/overleaf.git
synced 2024-09-16 02:52:31 -04:00
Teardown old project list frontend code (#11950)
* Remove frontend project list angular code (pugfiles + controllers) * Remove unused translation keys in every language GitOrigin-RevId: e0514721d6a32ca2de7d1be9433da3476ba1680c
This commit is contained in:
parent
c7a80f9228
commit
3e315eada1
33 changed files with 1 additions and 2370 deletions
|
@ -1,80 +0,0 @@
|
|||
extends ../layout
|
||||
|
||||
block vars
|
||||
- var suppressNavContentLinks = true
|
||||
|
||||
block append meta
|
||||
meta(name="ol-projects" data-type="json" content=projects)
|
||||
meta(name="ol-tags" data-type="json" content=tags)
|
||||
meta(name="ol-notifications" data-type="json" content=notifications)
|
||||
meta(name="ol-notificationsInstitution" data-type="json" content=notificationsInstitution)
|
||||
meta(name="ol-userAffiliations" data-type="json" content=userAffiliations)
|
||||
meta(name="ol-userEmails" data-type="json" content=userEmails)
|
||||
meta(name="ol-userHasNoSubscription" data-type="boolean" content=!!(settings.enableSubscriptions && !hasSubscription))
|
||||
meta(name="ol-allInReconfirmNotificationPeriods" data-type="json" content=allInReconfirmNotificationPeriods)
|
||||
meta(name="ol-reconfirmedViaSAML" content=reconfirmedViaSAML)
|
||||
meta(name="ol-survey-name" data-type="string" content=(survey ? survey.name : undefined))
|
||||
meta(name="ol-groupsAndEnterpriseBannerVariant" data-type="string" content=groupsAndEnterpriseBannerVariant)
|
||||
|
||||
block content
|
||||
|
||||
main.content.content-alt.project-list-page#main-content(
|
||||
ng-controller="ProjectPageController"
|
||||
role="main"
|
||||
)
|
||||
.system-messages(
|
||||
ng-cloak
|
||||
ng-controller="SystemMessagesController"
|
||||
)
|
||||
.system-message(
|
||||
ng-repeat="message in messages"
|
||||
ng-controller="SystemMessageController"
|
||||
ng-hide="hidden"
|
||||
)
|
||||
button(ng-hide="protected",ng-click="hide()").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
.system-message-content
|
||||
| {{htmlContent}}
|
||||
|
||||
include ../translations/translation_message
|
||||
|
||||
.project-list-content(event-tracking=settings.overleaf ? "loads_v2_dash" : "", onboard=settings.overleaf ? "true" : "", event-tracking-trigger=settings.overleaf ? "load" : "", event-tracking-mb="true", event-segmentation="{location: 'dash', v2_onboard: true}")
|
||||
.project-list-row(ng-cloak)
|
||||
.project-list-container.row(ng-if="projects.length > 0")
|
||||
.project-list-sidebar-wrapper.col-md-2.col-xs-3
|
||||
aside.project-list-sidebar
|
||||
include ./list/side-bar
|
||||
|
||||
if (survey && survey.name)
|
||||
.project-list-sidebar-survey(
|
||||
ng-if="shouldShowSurveyLink"
|
||||
ng-cloak
|
||||
)
|
||||
| #{survey.preText}
|
||||
a.project-list-sidebar-survey-link(
|
||||
href=survey.url
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
) #{survey.linkText}
|
||||
button.project-list-sidebar-survey-dismiss(
|
||||
type="button"
|
||||
title="Dismiss Overleaf survey"
|
||||
ng-click="dismissSurvey()"
|
||||
)
|
||||
span(
|
||||
aria-hidden="true"
|
||||
) ×
|
||||
|
||||
.project-list-main.col-md-10.col-xs-9
|
||||
include ./list/notifications
|
||||
include ./list/project-list
|
||||
|
||||
.project-list-empty.row(ng-if="projects.length === 0")
|
||||
.project-list-empty-col.col-md-offset-2.col-md-8.col-md-offset-2.col-xs-8.col-xs-offset-2
|
||||
include ./list/empty-project-list
|
||||
.row.row-spaced
|
||||
.col-sm-12
|
||||
include ./list/notifications
|
||||
|
||||
include ./list/modals
|
|
@ -1,112 +0,0 @@
|
|||
- var featuresPageVariant = splitTestVariants && splitTestVariants['features-page'] ? splitTestVariants['features-page'] : 'default'
|
||||
- var featuresLink = featuresPageVariant === 'new' ? "/about/features-overview" : "/learn/how-to/Overleaf_premium_features"
|
||||
|
||||
mixin current_plan()
|
||||
if (usersBestSubscription)
|
||||
.text-right.pull-right.current-plan
|
||||
case usersBestSubscription.type
|
||||
when 'free'
|
||||
+free_plan()
|
||||
when 'individual'
|
||||
if (usersBestSubscription.remainingTrialDays >= 0)
|
||||
+individual_plan_trial(usersBestSubscription.subscription, usersBestSubscription.plan, usersBestSubscription.remainingTrialDays)
|
||||
else
|
||||
+individual_plan_active(usersBestSubscription.subscription, usersBestSubscription.plan)
|
||||
when 'group'
|
||||
if (usersBestSubscription.remainingTrialDays >= 0)
|
||||
+group_plan_trial(usersBestSubscription.subscription, usersBestSubscription.plan, usersBestSubscription.remainingTrialDays)
|
||||
else
|
||||
+group_plan_active(usersBestSubscription.subscription, usersBestSubscription.plan)
|
||||
when 'commons'
|
||||
+commons_plan(usersBestSubscription.subscription, usersBestSubscription.plan)
|
||||
|
||||
mixin individual_plan_trial(subscription, plan, remainingTrialDays)
|
||||
a.current-plan-label(
|
||||
tooltip=translate('plan_tooltip', { plan: plan.name }),
|
||||
tooltip-placement="bottom"
|
||||
href=featuresLink
|
||||
event-tracking="features-page-link"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation={splitTest:"features-page", splitTestVariant: featuresPageVariant}
|
||||
)
|
||||
if (remainingTrialDays === 1)
|
||||
| !{translate('trial_last_day')}
|
||||
span.info-badge
|
||||
else
|
||||
| !{translate('trial_remaining_days', { days: remainingTrialDays })}
|
||||
span.info-badge
|
||||
|
||||
mixin individual_plan_active(subscription, plan)
|
||||
a.current-plan-label(
|
||||
tooltip=translate('plan_tooltip', {plan: plan.name}),
|
||||
tooltip-placement="bottom"
|
||||
href=featuresLink
|
||||
event-tracking="features-page-link"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation={splitTest:"features-page", splitTestVariant: featuresPageVariant}
|
||||
)
|
||||
| !{translate('premium_plan_label')}
|
||||
span.info-badge
|
||||
|
||||
mixin group_plan_trial(subscription, plan, remainingTrialDays)
|
||||
a.current-plan-label(
|
||||
tooltip=translate(subscription.teamName != null ? 'group_plan_with_name_tooltip' : 'group_plan_tooltip', { plan: plan.name, groupName: subscription.teamName }),
|
||||
tooltip-placement="bottom"
|
||||
href=featuresLink
|
||||
event-tracking="features-page-link"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation={splitTest:"features-page", splitTestVariant: featuresPageVariant}
|
||||
)
|
||||
if (remainingTrialDays === 1)
|
||||
| !{translate('trial_last_day')}
|
||||
span.info-badge
|
||||
else
|
||||
| !{translate('trial_remaining_days', { days: remainingTrialDays })}
|
||||
span.info-badge
|
||||
|
||||
mixin group_plan_active(subscription, plan)
|
||||
a.current-plan-label(
|
||||
tooltip=translate(subscription.teamName != null ? 'group_plan_with_name_tooltip' : 'group_plan_tooltip', { plan: plan.name, groupName: subscription.teamName }),
|
||||
tooltip-placement="bottom"
|
||||
href=featuresLink
|
||||
event-tracking="features-page-link"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation={splitTest:"features-page", splitTestVariant: featuresPageVariant}
|
||||
)
|
||||
| !{translate('premium_plan_label')}
|
||||
span.info-badge
|
||||
|
||||
mixin commons_plan(subscription, plan)
|
||||
a.current-plan-label(
|
||||
tooltip=translate('commons_plan_tooltip', { plan: plan.name, institution: subscription.name }),
|
||||
tooltip-placement="bottom"
|
||||
href=featuresLink
|
||||
event-tracking="features-page-link"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation={splitTest:"features-page", splitTestVariant: featuresPageVariant}
|
||||
)
|
||||
| !{translate('premium_plan_label')}
|
||||
span.info-badge
|
||||
|
||||
mixin free_plan()
|
||||
a.current-plan-label(
|
||||
tooltip=translate('free_plan_tooltip'),
|
||||
tooltip-placement="bottom"
|
||||
href=featuresLink
|
||||
event-tracking="features-page-link"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation={splitTest:"features-page", splitTestVariant: featuresPageVariant}
|
||||
)
|
||||
| !{translate('free_plan_label')}
|
||||
span.info-badge
|
||||
|
|
||||
a.btn.btn-primary(
|
||||
href="/user/subscription/plans?itm_referrer=project-dashboard-upgrade-prompt"
|
||||
ng-click="sendUpgradeButtonClickEvent()"
|
||||
) Upgrade
|
|
@ -1,82 +0,0 @@
|
|||
.row.row-spaced
|
||||
.col-xs-12
|
||||
.card.card-thin
|
||||
div.welcome.text-centered(ng-cloak)
|
||||
h2 #{translate("welcome_to_sl")}
|
||||
p #{translate("new_to_latex_look_at")}
|
||||
a(
|
||||
href="/templates"
|
||||
event-tracking="welcome-page-templates-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation='{"project-dashboard-react": "default"}'
|
||||
) #{translate("templates").toLowerCase()}
|
||||
| #{translate("or")}
|
||||
a(
|
||||
href="/learn"
|
||||
event-tracking="welcome-page-latex-help-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation='{"project-dashboard-react": "default"}'
|
||||
) #{translate("latex_help_guide")}
|
||||
|
||||
|
||||
.row
|
||||
.col-md-offset-4.col-md-4
|
||||
.dropdown.minimal-create-proj-dropdown(dropdown)
|
||||
a.btn.btn-primary.dropdown-toggle(
|
||||
href="#",
|
||||
data-toggle="dropdown",
|
||||
dropdown-toggle
|
||||
event-tracking="welcome-page-create-first-project-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation='{"project-dashboard-react": "default", "dropdownMenu": "main-button", "dropdownOpen": "null" }'
|
||||
)
|
||||
//- We can't know if dropdown is open or not, so will send "dropdownOpen: null" as a segmentation above
|
||||
| Create First Project
|
||||
|
||||
ul.dropdown-menu.minimal-create-proj-dropdown-menu(role="menu")
|
||||
li
|
||||
a(
|
||||
href,
|
||||
ng-click="openCreateProjectModal()"
|
||||
event-tracking="welcome-page-create-first-project-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation='{"project-dashboard-react": "default", "dropdownMenu": "blank-project", "dropdownOpen": "true" }'
|
||||
) #{translate("blank_project")}
|
||||
li
|
||||
a(
|
||||
href,
|
||||
ng-click="openCreateProjectModal('example')"
|
||||
event-tracking="welcome-page-create-first-project-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation='{"project-dashboard-react": "default", "dropdownMenu": "example-project", "dropdownOpen": "true" }'
|
||||
) #{translate("example_project")}
|
||||
li
|
||||
a(
|
||||
href,
|
||||
ng-click="openUploadProjectModal()"
|
||||
event-tracking="welcome-page-create-first-project-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation='{"project-dashboard-react": "default", "dropdownMenu": "upload-project", "dropdownOpen": "true" }'
|
||||
) #{translate("upload_project")}
|
||||
!= moduleIncludes("newProjectMenu", locals)
|
||||
if (templates)
|
||||
li.divider
|
||||
li.dropdown-header #{translate("templates")}
|
||||
each item in templates
|
||||
- var eventSegmentation = '{"project-dashboard-react": "default", "dropdownMenu":"' + item.trackingKey + '", "dropdownOpen": "true" }'
|
||||
li
|
||||
a.menu-indent(
|
||||
href=item.url
|
||||
event-tracking="welcome-page-create-first-project-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation=eventSegmentation
|
||||
) #{translate(item.name)}
|
||||
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
td.project-list-table-name-cell
|
||||
.project-list-table-name-container
|
||||
input.project-list-table-select-item(
|
||||
select-individual,
|
||||
type="checkbox",
|
||||
ng-model="project.selected"
|
||||
stop-propagation="click"
|
||||
aria-label=translate('select_project', {project: '{{ project.name }}'})
|
||||
)
|
||||
span.project-list-table-name
|
||||
a.project-list-table-name-link(
|
||||
ng-href="{{projectLink(project)}}"
|
||||
stop-propagation="click"
|
||||
) {{project.name}}
|
||||
span(
|
||||
ng-controller="TagListController"
|
||||
)
|
||||
.tag-label(
|
||||
ng-repeat='tag in project.tags'
|
||||
stop-propagation="click"
|
||||
)
|
||||
button.label.label-default.tag-label-name(
|
||||
ng-click="selectTag(tag)"
|
||||
aria-label="Select tag {{ tag.name }}"
|
||||
)
|
||||
i.fa.fa-circle(
|
||||
aria-hidden="true"
|
||||
ng-style="{ 'color': 'hsl({{ getHueForTagId(tag._id) }}, 70%, 45%)' }"
|
||||
)
|
||||
| {{tag.name}}
|
||||
button.label.label-default.tag-label-remove(
|
||||
ng-click="removeProjectFromTag(project, tag)"
|
||||
aria-label="Remove tag {{ tag.name }}"
|
||||
)
|
||||
span(aria-hidden="true") ×
|
||||
|
||||
td.project-list-table-owner-cell
|
||||
span.owner(ng-if='project.owner') {{getOwnerName(project)}}
|
||||
|
|
||||
i.fa.fa-question-circle.small(
|
||||
ng-if="hasGenericOwnerName()"
|
||||
tooltip="This project is owned by a user who hasn’t yet migrated their account to Overleaf v2"
|
||||
tooltip-append-to-body="true"
|
||||
aria-hidden="true"
|
||||
)
|
||||
span(ng-if="isLinkSharingProject(project)")
|
||||
|
|
||||
i.fa.fa-link.small(
|
||||
tooltip=translate("link_sharing")
|
||||
tooltip-placement="right"
|
||||
tooltip-append-to-body="true"
|
||||
aria-label=translate("link_sharing")
|
||||
)
|
||||
|
||||
td.project-list-table-lastupdated-cell
|
||||
span.last-modified(tooltip="{{project.lastUpdated | formatDate}}")
|
||||
| {{project.lastUpdated | fromNowDate}}
|
||||
span(ng-show='project.lastUpdatedBy')
|
||||
|
|
||||
| #{translate('by')}
|
||||
| {{getUserName(project.lastUpdatedBy)}}
|
||||
|
||||
|
||||
td.project-list-table-actions-cell
|
||||
div
|
||||
button.btn.btn-link.action-btn(
|
||||
ng-if="!(project.archived || project.trashed)"
|
||||
aria-label=translate('copy'),
|
||||
tooltip=translate('copy'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="openCloneProjectModal(project)"
|
||||
)
|
||||
i.icon.fa.fa-files-o(aria-hidden="true")
|
||||
button.btn.btn-link.action-btn(
|
||||
aria-label=translate('download'),
|
||||
tooltip=translate('download'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="download($event)"
|
||||
)
|
||||
i.icon.fa.fa-cloud-download(aria-hidden="true")
|
||||
button.btn.btn-link.action-btn(
|
||||
ng-if="!project.archived"
|
||||
aria-label=translate('archive'),
|
||||
tooltip=translate('archive'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="archive($event)"
|
||||
)
|
||||
i.icon.fa.fa-inbox(aria-hidden="true")
|
||||
button.btn.btn-link.action-btn(
|
||||
ng-if="!project.trashed"
|
||||
aria-label=translate('trash'),
|
||||
tooltip=translate('trash'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="trash($event)"
|
||||
)
|
||||
i.icon.fa.fa-trash(aria-hidden="true")
|
||||
button.btn.btn-link.action-btn(
|
||||
ng-if="project.archived && !project.trashed"
|
||||
aria-label=translate('unarchive'),
|
||||
tooltip=translate('unarchive'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="unarchive($event)"
|
||||
)
|
||||
i.icon.fa.fa-reply(aria-hidden="true")
|
||||
button.btn.btn-link.action-btn(
|
||||
ng-if="project.trashed && !project.archived"
|
||||
aria-label=translate('untrash'),
|
||||
tooltip=translate('untrash'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="untrash($event)"
|
||||
)
|
||||
i.icon.fa.fa-reply(aria-hidden="true")
|
||||
button.btn.btn-link.action-btn(
|
||||
ng-if="project.trashed && !project.archived && !isOwner()"
|
||||
aria-label=translate('leave'),
|
||||
tooltip=translate('leave'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="leave($event)"
|
||||
)
|
||||
i.icon.fa.fa-sign-out(aria-hidden="true")
|
||||
button.btn.btn-link.action-btn(
|
||||
ng-if="project.trashed && !project.archived && isOwner()"
|
||||
aria-label=translate('delete'),
|
||||
tooltip=translate('delete'),
|
||||
tooltip-placement="top",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="delete($event)"
|
||||
)
|
||||
i.icon.fa.fa-ban(aria-hidden="true")
|
|
@ -1,286 +0,0 @@
|
|||
include ../../_mixins/reconfirm_affiliation
|
||||
|
||||
.user-notifications(ng-controller="NotificationsController")
|
||||
ul.list-unstyled(
|
||||
ng-if="notifications.length > 0 && projects.length > 0",
|
||||
ng-cloak
|
||||
)
|
||||
li.notification-entry(
|
||||
ng-repeat="notification in notifications"
|
||||
)
|
||||
div(ng-switch="notification.templateKey" ng-hide="notification.hide")
|
||||
.alert.alert-info(
|
||||
ng-switch-when="notification_project_invite",
|
||||
ng-controller="ProjectInviteNotificationController"
|
||||
)
|
||||
.notification-body
|
||||
span(ng-show="!notification.accepted") !{translate("notification_project_invite_message", { userName: "{{ userName }}", projectName: "{{ projectName }}" })}
|
||||
span(ng-show="notification.accepted") !{translate("notification_project_invite_accepted_message", { projectName: "{{ projectName }}" })}
|
||||
.notification-action
|
||||
a.pull-right.btn.btn-sm.btn-info(
|
||||
ng-show="notification.accepted",
|
||||
href="/project/{{ notification.messageOpts.projectId }}"
|
||||
) #{translate("open_project")}
|
||||
a.pull-right.btn.btn-sm.btn-info(
|
||||
href,
|
||||
ng-click="accept()",
|
||||
ng-disabled="notification.inflight",
|
||||
ng-show="!notification.accepted"
|
||||
)
|
||||
span(ng-show="!notification.inflight") #{translate("join_project")}
|
||||
span(ng-show="notification.inflight")
|
||||
i.fa.fa-fw.fa-spinner.fa-spin(aria-hidden="true")
|
||||
|
|
||||
| #{translate("joining")}…
|
||||
.notification-close
|
||||
button(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
.alert.alert-info(
|
||||
ng-switch-when="wfh_2020_upgrade_offer"
|
||||
)
|
||||
.notification-body
|
||||
span Important notice: Your free WFH2020 upgrade came to an end on June 30th 2020. We're still providing a number of special initiatives to help you continue collaborating throughout 2020.
|
||||
.notification-action
|
||||
a.pull-right.btn.btn-sm.btn-info(href="https://www.overleaf.com/events/wfh2020") View
|
||||
.notification-close
|
||||
button(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
.alert.alert-info(
|
||||
ng-switch-when="notification_ip_matched_affiliation"
|
||||
ng-if="notification.messageOpts.ssoEnabled"
|
||||
)
|
||||
.notification-body
|
||||
| !{translate("looks_like_youre_at", {institutionName: '{{notification.messageOpts.university_name}}'}, ['strong'])}
|
||||
br
|
||||
| !{translate("you_can_now_log_in_sso", {}, ['strong'])}
|
||||
br
|
||||
| #{translate("link_institutional_email_get_started", {}, ['strong'])}
|
||||
a(
|
||||
ng-href="{{notification.messageOpts.portalPath || 'https://www.overleaf.com/learn/how-to/Institutional_Login'}}"
|
||||
) #{translate("find_out_more_nt")}
|
||||
.notification-action
|
||||
a.pull-right.btn.btn-sm.btn-info(
|
||||
ng-href=`{{samlInitPath}}?university_id={{notification.messageOpts.institutionId}}&auto=/project`
|
||||
)
|
||||
| #{translate("link_account")}
|
||||
.notification-close
|
||||
button.btn-sm(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
.alert.alert-info(
|
||||
ng-switch-when="notification_ip_matched_affiliation"
|
||||
ng-if="!notification.messageOpts.ssoEnabled"
|
||||
)
|
||||
.notification-body
|
||||
| !{translate("looks_like_youre_at", {institutionName: '{{notification.messageOpts.university_name}}'}, ['strong'])}
|
||||
br
|
||||
| !{translate("did_you_know_institution_providing_professional", {institutionName: '{{notification.messageOpts.university_name}}'}, ['strong'])}
|
||||
br
|
||||
| #{translate("add_email_to_claim_features")}
|
||||
.notification-action
|
||||
a.pull-right.btn.btn-sm.btn-info(
|
||||
href="/user/settings"
|
||||
) #{translate("add_affiliation")}
|
||||
.notification-close
|
||||
button.btn-sm(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
.alert.alert-danger(
|
||||
ng-switch-when="notification_tpds_file_limit"
|
||||
)
|
||||
.notification-body
|
||||
| Error: Your project
|
||||
strong {{ notification.messageOpts.projectName }}
|
||||
| has gone over the 2000 file limit using an integration (e.g. Dropbox or GitHub) <br/>
|
||||
| Please decrease the size of your project to prevent further errors.
|
||||
.notification-action
|
||||
a.pull-right.btn.btn-sm.btn-info(href="/user/settings")
|
||||
| Account Settings
|
||||
.notification-close
|
||||
button.btn-sm(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
.alert.alert-warning(
|
||||
ng-switch-when="notification_dropbox_duplicate_project_names"
|
||||
)
|
||||
.notification-body
|
||||
p()
|
||||
| !{translate("dropbox_duplicate_project_names", { projectName: '{{notification.messageOpts.projectName}}'}, ['strong'])}
|
||||
p()
|
||||
| !{translate("dropbox_duplicate_project_names_suggestion", {}, ['strong'])}
|
||||
|
|
||||
a(href="/learn/how-to/Dropbox_Synchronization#Troubleshooting") #{translate("learn_more")}
|
||||
|.
|
||||
.notification-close
|
||||
button.btn-sm(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
.alert.alert-info(
|
||||
ng-switch-when="notification_dropbox_unlinked_due_to_lapsed_reconfirmation"
|
||||
)
|
||||
.notification-body
|
||||
if user.features.dropbox
|
||||
| !{translate("dropbox_unlinked_premium_feature", {}, ['strong'])}
|
||||
| !{translate("can_now_relink_dropbox", {}, [{name: 'a', attrs: {href: '/user/settings#project-sync' }}])}
|
||||
else
|
||||
| !{translate("dropbox_unlinked_premium_feature", {}, ['strong'])}
|
||||
| !{translate("confirm_affiliation_to_relink_dropbox")}
|
||||
|
|
||||
a(href="/learn/how-to/Institutional_Email_Reconfirmation") #{translate("learn_more")}
|
||||
.notification-close
|
||||
button.btn-sm(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
.alert.alert-info(
|
||||
ng-switch-default
|
||||
)
|
||||
span(ng-bind-html="notification.html").notification-body
|
||||
.notification-close
|
||||
button(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
ul.list-unstyled(
|
||||
ng-if="notificationsInstitution.length > 0",
|
||||
ng-cloak
|
||||
)
|
||||
li.notification-entry(
|
||||
ng-repeat="notification in notificationsInstitution"
|
||||
)
|
||||
div(ng-switch="notification.templateKey" ng-hide="notification.hide")
|
||||
.alert.alert-info(
|
||||
ng-switch-when="notification_institution_sso_available"
|
||||
)
|
||||
.notification-body
|
||||
p !{translate("can_link_institution_email_acct_to_institution_acct", {appName: settings.appName, email: "{{notification.email}}", institutionName: "{{notification.institutionName}}"})}
|
||||
div !{translate("doing_this_allow_log_in_through_institution", {appName: settings.appName})}
|
||||
a(href="/learn/how-to/Institutional_Login") #{translate("learn_more")}
|
||||
.notification-action
|
||||
a.btn.btn-sm.btn-info(ng-href="{{samlInitPath}}?university_id={{notification.institutionId}}&auto=/project&email={{notification.email}}")
|
||||
| #{translate('link_account')}
|
||||
|
||||
.alert.alert-info(
|
||||
ng-switch-when="notification_institution_sso_linked"
|
||||
)
|
||||
.notification-body
|
||||
div !{translate("account_has_been_link_to_institution_account", {appName: settings.appName, email: "{{notification.email}}", institutionName: "{{notification.institutionName}}"})}
|
||||
.notification-close
|
||||
button(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
.alert.alert-warning(
|
||||
ng-switch-when="notification_institution_sso_non_canonical"
|
||||
)
|
||||
.notification-body
|
||||
div
|
||||
i.fa.fa-fw.fa-exclamation-triangle(aria-hidden="true")
|
||||
| !{translate("tried_to_log_in_with_email", {email: "{{notification.requestedEmail}}"})} !{translate("in_order_to_match_institutional_metadata_associated", {email: "{{notification.institutionEmail}}"})}
|
||||
.notification-close
|
||||
button(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
.alert.alert-info(
|
||||
ng-switch-when="notification_institution_sso_already_registered"
|
||||
)
|
||||
.notification-body
|
||||
| !{translate("tried_to_register_with_email", {appName: settings.appName, email: "{{notification.email}}"})}
|
||||
| #{translate("we_logged_you_in")}
|
||||
.notification-action
|
||||
a.btn.btn-sm.btn-info(href="/learn/how-to/Institutional_Login")
|
||||
| #{translate("find_out_more")}
|
||||
.notification-close
|
||||
button(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
.alert.alert-danger(ng-switch-when="notification_institution_sso_error")
|
||||
.notification-body
|
||||
div
|
||||
i.fa.fa-fw.fa-exclamation-triangle(aria-hidden="true")
|
||||
| #{translate("generic_something_went_wrong")}.
|
||||
div(ng-if="notification.error.translatedMessage" ng-bind-html="notification.error.translatedMessage")
|
||||
div(ng-else="notification.error.message") {{ notification.error.message}}
|
||||
div(ng-if="notification.error.tryAgain") #{translate("try_again")}.
|
||||
|
||||
.notification-close
|
||||
button(ng-click="dismiss(notification)").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
||||
|
||||
ul.list-unstyled(
|
||||
ng-controller="EmailNotificationController",
|
||||
ng-cloak
|
||||
)
|
||||
li.notification-entry(
|
||||
ng-repeat="userEmail in userEmails",
|
||||
ng-if="showConfirmEmail(userEmail) && projects.length > 0"
|
||||
)
|
||||
.alert.alert-warning
|
||||
.notification-body
|
||||
div(ng-if="!userEmail.confirmationInflight")
|
||||
| #{translate("please_confirm_email", {emailAddress: "{{ userEmail.email }}"})}
|
||||
|
|
||||
a(
|
||||
href
|
||||
ng-click="resendConfirmationEmail(userEmail)"
|
||||
) (#{translate('resend_confirmation_email')})
|
||||
div(ng-if="userEmail.confirmationInflight")
|
||||
i.fa.fa-spinner.fa-spin(aria-hidden="true")
|
||||
|
|
||||
| #{translate('resending_confirmation_email')}…
|
||||
div(ng-if="!userEmail.confirmationInflight && userEmail.error" aria-live="polite")
|
||||
span(ng-if="userEmail.errorMessage") {{ userEmail.errorMessage }}
|
||||
span(ng-if="!userEmail.errorMessage") #{translate('generic_something_went_wrong')}
|
||||
|
||||
ui.list-unstyled(ng-controller="UserAffiliationsReconfirmController")
|
||||
li.notification-entry(
|
||||
ng-repeat="userEmail in allInReconfirmNotificationPeriods"
|
||||
)
|
||||
.alert.alert-info()
|
||||
+reconfirmAffiliationNotification('/project')
|
||||
|
||||
li.notification-entry(
|
||||
ng-repeat="userEmail in userEmails"
|
||||
ng-if="userEmail.samlIdentifier && userEmail.samlIdentifier.providerId === reconfirmedViaSAML"
|
||||
)
|
||||
+reconfirmedAffiliationNotification()
|
||||
|
||||
if showGroupsAndEnterpriseBanner
|
||||
- var eventSegmentation = '{"location": "dashboard-banner", "variant":"' + groupsAndEnterpriseBannerVariant + '" }'
|
||||
ul.list-unstyled(
|
||||
ng-controller="GroupsAndEnterpriseBannerController",
|
||||
ng-cloak
|
||||
)
|
||||
li.notification-entry(
|
||||
ng-if="isVariantValid && !hasDismissedGroupsAndEnterpriseBanner && projects.length > 0"
|
||||
event-tracking="groups-and-enterprise-banner-prompt"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="load"
|
||||
event-segmentation=eventSegmentation
|
||||
)
|
||||
.alert.alert-info
|
||||
.notification-body(ng-switch="groupsAndEnterpriseBannerVariant")
|
||||
span(ng-switch-when="did-you-know") #{translate("did_you_know_that_overleaf_offers")}
|
||||
span(ng-switch-when="on-premise") Overleaf On-Premises: Does your company want to keep its data within its firewall? Overleaf offers Server Pro, an on-premises solution for companies. Get in touch to learn more.
|
||||
span(ng-switch-when="people") Other people at your company may already be using Overleaf. Save money with Overleaf group and company-wide subscriptions. Request more information.
|
||||
span(ng-switch-when="FOMO") Why do Fortune 500 companies and top research institutions trust Overleaf to streamline their collaboration? Get in touch to learn more.
|
||||
.notification-action
|
||||
a.pull-right.btn.btn-sm.btn-info(
|
||||
href="/for/contact-sales{{urlVariantSuffix}}"
|
||||
target="_blank"
|
||||
event-tracking="groups-and-enterprise-banner-click"
|
||||
event-tracking-mb="true"
|
||||
event-tracking-trigger="click"
|
||||
event-segmentation=eventSegmentation
|
||||
) #{translate("contact_sales")}
|
||||
.notification-close
|
||||
button(ng-click="dismiss()").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
|
@ -1,223 +0,0 @@
|
|||
include ./_current_plan_mixins
|
||||
|
||||
.row
|
||||
.col-xs-12(ng-cloak)
|
||||
form.project-search.form-horizontal(role="form")
|
||||
.form-group.has-feedback.has-feedback-left.col-md-7.col-xs-12
|
||||
input.form-control.col-md-7.col-xs-12(
|
||||
placeholder=translate('search_projects')+"…",
|
||||
aria-label=translate('search_projects')+"…",
|
||||
autofocus='autofocus',
|
||||
ng-model="searchText.value",
|
||||
focus-on='search:clear',
|
||||
ng-keyup="searchProjects()"
|
||||
)
|
||||
i.fa.fa-search.form-control-feedback-left(aria-hidden="true")
|
||||
i.fa.fa-times.form-control-feedback(
|
||||
ng-click="clearSearchText()",
|
||||
style="cursor: pointer;",
|
||||
ng-show="searchText.value.length > 0"
|
||||
aria-hidden="true"
|
||||
)
|
||||
button.sr-only(
|
||||
type="button"
|
||||
ng-click="clearSearchText()"
|
||||
ng-show="searchText.value.length > 0"
|
||||
) #{translate('clear_search')}
|
||||
|
||||
.project-tools(ng-cloak)
|
||||
.project-list-upgrade-prompt(ng-cloak ng-hide="selectedProjects.length > 0")
|
||||
+current_plan()
|
||||
.btn-toolbar
|
||||
.btn-group(ng-hide="selectedProjects.length < 1")
|
||||
a.btn.btn-secondary(
|
||||
href,
|
||||
aria-label=translate('download'),
|
||||
tooltip=translate('download'),
|
||||
tooltip-placement="bottom",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="downloadSelectedProjects()"
|
||||
)
|
||||
i.fa.fa-cloud-download(aria-hidden="true")
|
||||
a.btn.btn-secondary(
|
||||
href,
|
||||
ng-if="filter !== 'archived'"
|
||||
aria-label=translate("archive"),
|
||||
tooltip=translate("archive"),
|
||||
tooltip-placement="bottom",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="openArchiveProjectsModal()"
|
||||
)
|
||||
i.fa.fa-inbox(aria-hidden="true")
|
||||
a.btn.btn-secondary(
|
||||
href,
|
||||
ng-if="filter !== 'trashed'"
|
||||
aria-label=translate("trash"),
|
||||
tooltip=translate("trash"),
|
||||
tooltip-placement="bottom",
|
||||
tooltip-append-to-body="true",
|
||||
ng-click="openTrashProjectsModal()"
|
||||
)
|
||||
i.fa.fa-trash(aria-hidden="true")
|
||||
.btn-group.dropdown(
|
||||
ng-hide="selectedProjects.length < 1 || filter === 'archived' || filter === 'trashed'",
|
||||
dropdown
|
||||
)
|
||||
a.btn.btn-secondary.dropdown-toggle(
|
||||
href,
|
||||
data-toggle="dropdown",
|
||||
dropdown-toggle,
|
||||
tooltip=translate('add_to_folders'),
|
||||
tooltip-append-to-body="true",
|
||||
tooltip-placement="bottom"
|
||||
)
|
||||
i.fa.fa-folder-open
|
||||
|
|
||||
span.caret
|
||||
span.sr-only #{translate('add_to_folders')}
|
||||
ul.dropdown-menu.dropdown-menu-right.js-tags-dropdown-menu.tags-dropdown-menu(
|
||||
role="menu"
|
||||
ng-controller="TagListController"
|
||||
)
|
||||
li.dropdown-header #{translate("add_to_folder")}
|
||||
li(
|
||||
ng-repeat="tag in tags | orderBy:'name'",
|
||||
ng-controller="TagDropdownItemController"
|
||||
)
|
||||
a(href="#", ng-click="addOrRemoveProjectsFromTag()", stop-propagation="click")
|
||||
i.fa(
|
||||
ng-class="{\
|
||||
'fa-check-square-o': areSelectedProjectsInTag == true,\
|
||||
'fa-square-o': areSelectedProjectsInTag == false,\
|
||||
'fa-minus-square-o': areSelectedProjectsInTag == 'partial'\
|
||||
}"
|
||||
)
|
||||
span.sr-only Add or remove project from tag
|
||||
| {{tag.name}}
|
||||
li.divider
|
||||
li
|
||||
a(href, ng-click="openNewTagModal()", stop-propagation="click") #{translate("create_new_folder")}
|
||||
|
||||
.btn-group.dropdown(
|
||||
ng-hide="selectedProjects.length != 1 || filter === 'archived' || filter === 'trashed'",
|
||||
dropdown
|
||||
)
|
||||
a.btn.btn-secondary.dropdown-toggle(
|
||||
href,
|
||||
data-toggle="dropdown",
|
||||
dropdown-toggle
|
||||
) #{translate("more")}
|
||||
span.caret
|
||||
ul.dropdown-menu.dropdown-menu-right(role="menu")
|
||||
li(ng-show="getFirstSelectedProject().accessLevel == 'owner'")
|
||||
a(
|
||||
href,
|
||||
ng-click="openRenameProjectModal()"
|
||||
) #{translate("rename")}
|
||||
li
|
||||
a(
|
||||
href,
|
||||
ng-click="openCloneProjectModal(getFirstSelectedProject())"
|
||||
) #{translate("make_copy")}
|
||||
|
||||
.btn-group(ng-show="filter === 'archived' && selectedProjects.length > 0")
|
||||
a.btn.btn-secondary(
|
||||
href,
|
||||
data-original-title=translate("unarchive"),
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
ng-click="unarchiveProjects(selectedProjects)"
|
||||
) #{translate("unarchive")}
|
||||
|
||||
.btn-group(ng-show="filter === 'trashed' && selectedProjects.length > 0")
|
||||
a.btn.btn-secondary(
|
||||
href,
|
||||
data-original-title=translate("untrash"),
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
ng-click="untrashProjects(selectedProjects)"
|
||||
) #{translate("untrash")}
|
||||
|
||||
.btn-group(ng-show="filter === 'trashed' && selectedProjects.length > 0")
|
||||
a.btn.btn-danger(
|
||||
href,
|
||||
ng-if="hasLeavableProjectsSelected() && !hasDeletableProjectsSelected()",
|
||||
data-original-title=translate('leave'),
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
ng-click="openLeaveProjectsModal()"
|
||||
) #{translate("leave")}
|
||||
|
||||
a.btn.btn-danger(
|
||||
href,
|
||||
ng-if="hasDeletableProjectsSelected() && !hasLeavableProjectsSelected()",
|
||||
data-original-title=translate('delete'),
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
ng-click="openDeleteProjectsModal()"
|
||||
) #{translate("delete")}
|
||||
|
||||
a.btn.btn-danger(
|
||||
href,
|
||||
ng-if="hasDeletableProjectsSelected() && hasLeavableProjectsSelected()",
|
||||
data-original-title=translate('delete_and_leave'),
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
ng-click="openLeaveOrDeleteProjectsModal()"
|
||||
) #{translate("delete_and_leave")}
|
||||
|
||||
.row.row-spaced
|
||||
.col-xs-12
|
||||
.card.card-thin.project-list-card
|
||||
ul.list-unstyled.project-list.structured-list(
|
||||
select-all-list,
|
||||
ng-if="projects.length > 0",
|
||||
max-height="projectListHeight - 25",
|
||||
ng-cloak
|
||||
)
|
||||
table.project-list-table
|
||||
tr.project-list-table-header-row
|
||||
th.project-list-table-name-cell
|
||||
.project-list-table-name-container
|
||||
input.project-list-table-select-item(
|
||||
select-all,
|
||||
type="checkbox"
|
||||
aria-label=translate('select_all_projects')
|
||||
)
|
||||
span.header.clickable.project-list-table-name(ng-click="changePredicate('name')") #{translate("title")}
|
||||
i.tablesort.fa(ng-class="getSortIconClass('name')" aria-hidden="true")
|
||||
button.sr-only(ng-click="changePredicate('name')") Sort by #{translate("title")}
|
||||
th.project-list-table-owner-cell
|
||||
span.header.clickable(ng-click="changePredicate('ownerName')") #{translate("owner")}
|
||||
i.tablesort.fa(ng-class="getSortIconClass('ownerName')" aria-hidden="true")
|
||||
button.sr-only(ng-click="changePredicate('ownerName')") Sort by #{translate("owner")}
|
||||
th.project-list-table-lastupdated-cell
|
||||
span.header.clickable(ng-click="changePredicate('lastUpdated')") #{translate("last_modified")}
|
||||
i.tablesort.fa(ng-class="getSortIconClass('lastUpdated')" aria-hidden="true")
|
||||
button.sr-only(ng-click="changePredicate('lastUpdated')") Sort by #{translate("last_modified")}
|
||||
th.project-list-table-actions-cell
|
||||
span.header #{translate("actions")}
|
||||
tr.project-list-table-row(
|
||||
ng-repeat="project in visibleProjects | orderBy:getValueForCurrentPredicate:reverse:comparator",
|
||||
ng-controller="ProjectListItemController"
|
||||
select-row
|
||||
)
|
||||
include ./item
|
||||
tr(
|
||||
ng-if="visibleProjects.length == 0",
|
||||
ng-cloak
|
||||
)
|
||||
td(colspan="4").project-list-table-no-projects-cell
|
||||
span.small #{translate("no_projects")}
|
||||
|
||||
div.welcome.text-centered(ng-if="projects.length == 0", ng-cloak)
|
||||
h2 #{translate("welcome_to_sl")}
|
||||
p #{translate("new_to_latex_look_at")}
|
||||
a(href="/templates") #{translate("templates").toLowerCase()}
|
||||
| #{translate("or")}
|
||||
a(href="/learn") #{translate("latex_help_guide")}
|
||||
| ,
|
||||
br
|
||||
| #{translate("or_create_project_left")}
|
||||
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
.dropdown(
|
||||
dropdown
|
||||
dropdown-append-to-body
|
||||
)
|
||||
a.btn.btn-primary.sidebar-new-proj-btn.dropdown-toggle(
|
||||
href="#",
|
||||
data-toggle="dropdown",
|
||||
dropdown-toggle
|
||||
)
|
||||
| #{translate("new_project")}
|
||||
|
||||
ul.dropdown-menu(role="menu")
|
||||
li
|
||||
a(
|
||||
href,
|
||||
ng-click="openCreateProjectModal()"
|
||||
) #{translate("blank_project")}
|
||||
li
|
||||
a(
|
||||
href,
|
||||
ng-click="openCreateProjectModal('example')"
|
||||
) #{translate("example_project")}
|
||||
li
|
||||
a(
|
||||
href,
|
||||
ng-click="openUploadProjectModal()"
|
||||
) #{translate("upload_project")}
|
||||
!= moduleIncludes("newProjectMenu", locals)
|
||||
|
||||
if portalTemplates.length > 0
|
||||
//- portalTemplates is set in ProjectController
|
||||
li.divider
|
||||
li.dropdown-header #{translate("institution")} #{translate("templates")}
|
||||
for portal in portalTemplates
|
||||
li
|
||||
a.menu-indent(
|
||||
href=portal.url + "#templates",
|
||||
ng-non-bindable
|
||||
) #{portal.name}
|
||||
|
||||
|
||||
|
||||
if (templates)
|
||||
//- templates is an express local var, via settings.templateLinks
|
||||
li.divider
|
||||
li.dropdown-header #{translate("templates")}
|
||||
each item in templates
|
||||
li
|
||||
a.menu-indent(href=item.url) #{translate(item.name)}
|
||||
|
||||
.row-spaced(ng-if="projects.length > 0", ng-cloak)
|
||||
ul.list-unstyled.folders-menu(
|
||||
ng-controller="TagListController"
|
||||
)
|
||||
li(ng-class="{active: (filter == 'all')}", ng-click="filterProjects('all')")
|
||||
a(href) #{translate("all_projects")}
|
||||
li(ng-class="{active: (filter == 'owned')}", ng-click="filterProjects('owned')")
|
||||
a(href) #{translate("your_projects")}
|
||||
li(ng-class="{active: (filter == 'shared')}", ng-click="filterProjects('shared')")
|
||||
a(href) #{translate("shared_with_you")}
|
||||
li(ng-class="{active: (filter == 'archived')}", ng-click="filterProjects('archived')")
|
||||
a(href) #{translate("archived_projects")}
|
||||
li(ng-class="{active: (filter == 'trashed')}", ng-click="filterProjects('trashed')")
|
||||
a(href) #{translate("trashed_projects")}
|
||||
li.separator
|
||||
h2 #{translate("tags_slash_folders")}
|
||||
li.tag(ng-cloak)
|
||||
a.tag-name(href, ng-click="openNewTagModal()")
|
||||
i.fa.fa-fw.fa-plus(aria-hidden="true")
|
||||
span.name #{translate("new_folder")}
|
||||
li.tag(
|
||||
ng-repeat="tag in tags | orderBy:'name'",
|
||||
ng-class="{active: tag.selected}",
|
||||
ng-cloak,
|
||||
ng-click="selectTag(tag)"
|
||||
)
|
||||
a.tag-name(href)
|
||||
i.icon.fa.fa-fw(
|
||||
ng-class="{\
|
||||
'fa-folder-open': tag.selected,\
|
||||
'fa-folder': !tag.selected\
|
||||
}"
|
||||
ng-style="{ 'color': 'hsl({{ getHueForTagId(tag._id) }}, 70%, 45%)' }"
|
||||
aria-hidden="true"
|
||||
)
|
||||
span.name {{tag.name}}
|
||||
span.subdued ({{countProjectsForTag(tag)}})
|
||||
|
||||
span.dropdown.tag-menu(dropdown)
|
||||
a.dropdown-toggle(
|
||||
href="#",
|
||||
data-toggle="dropdown",
|
||||
dropdown-toggle,
|
||||
stop-propagation="click"
|
||||
)
|
||||
span.caret
|
||||
ul.dropdown-menu.dropdown-menu-right(
|
||||
role="menu"
|
||||
)
|
||||
li
|
||||
a(href, ng-click="renameTag(tag)", stop-propagation="click")
|
||||
| #{translate("rename")}
|
||||
li
|
||||
a(href, ng-click="deleteTag(tag)", stop-propagation="click")
|
||||
| #{translate("delete")}
|
||||
li.tag.untagged(
|
||||
ng-if="tags.length",
|
||||
ng-cloak,
|
||||
ng-click="selectUntagged()"
|
||||
ng-class="{active: filter === 'untagged'}",
|
||||
)
|
||||
a.tag-name(href)
|
||||
span.name
|
||||
| #{translate("uncategorized")}
|
||||
span.subdued ({{ nUntagged }})
|
||||
|
||||
.row-spaced(ng-if="projects.length == 0", ng-cloak)
|
||||
.first-project
|
||||
div
|
||||
i.fa.fa-arrow-up.fa-2x(aria-hidden="true")
|
||||
div
|
||||
strong #{translate("create_your_first_project")}
|
||||
|
||||
if (isOverleaf)
|
||||
span(ng-controller="LeftHandMenuPromoController", ng-cloak)
|
||||
|
||||
.row-spaced#userProfileInformation(ng-if="hasProjects")
|
||||
div(ng-hide="withAffiliations", ng-cloak)
|
||||
hr
|
||||
.text-centered.add-affiliation
|
||||
p Are you affiliated with an institution?
|
||||
|
||||
a.btn.btn-secondary-info.btn-secondary(
|
||||
href="/user/settings"
|
||||
) Add Affiliation
|
|
@ -1,8 +0,0 @@
|
|||
if (typeof(suggestedLanguageSubdomainConfig) != "undefined")
|
||||
span(ng-controller="TranslationsPopupController", ng-cloak)
|
||||
.translations-message(ng-hide="hidei18nNotification")
|
||||
a(href=suggestedLanguageSubdomainConfig.url+currentUrl) !{translate("click_here_to_view_sl_in_lng", {lngName: translate(suggestedLanguageSubdomainConfig.lngCode)}, ['strong'])}
|
||||
img(src=buildImgPath("flags/24/" + suggestedLanguageSubdomainConfig.lngCode + ".png"))
|
||||
button(ng-click="dismiss()").close.pull-right
|
||||
span(aria-hidden="true") ×
|
||||
span.sr-only #{translate("close")}
|
|
@ -820,7 +820,7 @@ module.exports = {
|
|||
reportOnly: process.env.CSP_REPORT_ONLY === 'true',
|
||||
reportPercentage: parseFloat(process.env.CSP_REPORT_PERCENTAGE) || 0,
|
||||
reportUri: process.env.CSP_REPORT_URI,
|
||||
exclude: ['app/views/project/editor', 'app/views/project/list'],
|
||||
exclude: ['app/views/project/editor', 'app/views/project/list-react'],
|
||||
},
|
||||
|
||||
unsupportedBrowsers: {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
import './project-list'
|
||||
import './modal-controllers'
|
||||
import './tag-controllers'
|
||||
import './notifications-controller'
|
||||
import './left-hand-menu-promo-controller'
|
||||
import '../../services/queued-http'
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import App from '../../base'
|
||||
|
||||
export default App.controller(
|
||||
'LeftHandMenuPromoController',
|
||||
function ($scope, UserAffiliationsDataService, eventTracking) {
|
||||
$scope.hasProjects = window.data.projects.length > 0
|
||||
|
||||
const _userHasNoAffiliation = function () {
|
||||
$scope.withAffiliations = window.data.userAffiliations.length > 0
|
||||
}
|
||||
|
||||
_userHasNoAffiliation()
|
||||
}
|
||||
)
|
|
@ -12,45 +12,6 @@
|
|||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
import App from '../../base'
|
||||
App.controller(
|
||||
'RenameProjectModalController',
|
||||
function ($scope, $modalInstance, $timeout, project, queuedHttp) {
|
||||
$scope.inputs = { projectName: project.name }
|
||||
|
||||
$scope.state = {
|
||||
inflight: false,
|
||||
error: false,
|
||||
}
|
||||
|
||||
$modalInstance.opened.then(() =>
|
||||
$timeout(() => $scope.$broadcast('open'), 200)
|
||||
)
|
||||
|
||||
$scope.rename = function () {
|
||||
$scope.state.inflight = true
|
||||
$scope.state.error = false
|
||||
return $scope
|
||||
.renameProject(project, $scope.inputs.projectName)
|
||||
.then(function () {
|
||||
$scope.state.inflight = false
|
||||
$scope.state.error = false
|
||||
return $modalInstance.close()
|
||||
})
|
||||
.catch(function (response) {
|
||||
const { data, status } = response
|
||||
$scope.state.inflight = false
|
||||
if (status === 400) {
|
||||
return ($scope.state.error = { message: data })
|
||||
} else {
|
||||
return ($scope.state.error = true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return ($scope.cancel = () => $modalInstance.dismiss('cancel'))
|
||||
}
|
||||
)
|
||||
|
||||
App.controller(
|
||||
'CloneProjectModalController',
|
||||
function ($scope, $modalInstance, $timeout, project) {
|
||||
|
@ -88,45 +49,6 @@ App.controller(
|
|||
}
|
||||
)
|
||||
|
||||
App.controller(
|
||||
'NewProjectModalController',
|
||||
function ($scope, $modalInstance, $timeout, template) {
|
||||
$scope.inputs = { projectName: '' }
|
||||
$scope.state = {
|
||||
inflight: false,
|
||||
error: false,
|
||||
}
|
||||
|
||||
$modalInstance.opened.then(() =>
|
||||
$timeout(() => $scope.$broadcast('open'), 200)
|
||||
)
|
||||
|
||||
$scope.create = function () {
|
||||
$scope.state.inflight = true
|
||||
$scope.state.error = false
|
||||
return $scope
|
||||
.createProject($scope.inputs.projectName, template)
|
||||
.then(function (response) {
|
||||
const { data } = response
|
||||
$scope.state.inflight = false
|
||||
$scope.state.error = false
|
||||
return $modalInstance.close(data.project_id)
|
||||
})
|
||||
.catch(function (response) {
|
||||
const { data, status } = response
|
||||
$scope.state.inflight = false
|
||||
if (status === 400) {
|
||||
return ($scope.state.error = { message: data })
|
||||
} else {
|
||||
return ($scope.state.error = true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return ($scope.cancel = () => $modalInstance.dismiss('cancel'))
|
||||
}
|
||||
)
|
||||
|
||||
App.controller(
|
||||
'ArchiveTrashLeaveOrDeleteProjectsModalController',
|
||||
function ($scope, $modalInstance, $timeout, projects, action) {
|
||||
|
@ -139,33 +61,3 @@ App.controller(
|
|||
$scope.cancel = () => $modalInstance.dismiss('cancel')
|
||||
}
|
||||
)
|
||||
|
||||
App.controller(
|
||||
'UploadProjectModalController',
|
||||
function ($scope, $modalInstance, $timeout) {
|
||||
$scope.cancel = () => $modalInstance.dismiss('cancel')
|
||||
|
||||
return ($scope.onComplete = function (error, name, response) {
|
||||
if (response.project_id != null) {
|
||||
return (window.location = `/project/${response.project_id}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
App.controller(
|
||||
'V1ImportModalController',
|
||||
function ($scope, $modalInstance, project) {
|
||||
$scope.project = project
|
||||
|
||||
return ($scope.dismiss = () => $modalInstance.dismiss('cancel'))
|
||||
}
|
||||
)
|
||||
|
||||
export default App.controller(
|
||||
'ShowErrorModalController',
|
||||
function ($scope, $modalInstance, error) {
|
||||
$scope.error = error
|
||||
return ($scope.cancel = () => $modalInstance.dismiss('cancel'))
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
import App from '../../base'
|
||||
import getMeta from '../../utils/meta'
|
||||
|
||||
const ExposedSettings = window.ExposedSettings
|
||||
App.controller('NotificationsController', function ($scope, $http) {
|
||||
for (const notification of $scope.notifications || []) {
|
||||
notification.hide = false
|
||||
}
|
||||
|
||||
$scope.samlInitPath = ExposedSettings.samlInitPath
|
||||
|
||||
$scope.dismiss = notification => {
|
||||
if (!notification._id) {
|
||||
notification.hide = true
|
||||
return
|
||||
}
|
||||
$http({
|
||||
url: `/notifications/${notification._id}`,
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-Csrf-Token': window.csrfToken,
|
||||
},
|
||||
}).then(() => (notification.hide = true))
|
||||
}
|
||||
})
|
||||
|
||||
App.controller(
|
||||
'GroupsAndEnterpriseBannerController',
|
||||
function ($scope, localStorage) {
|
||||
$scope.hasDismissedGroupsAndEnterpriseBanner = localStorage(
|
||||
'has_dismissed_groups_and_enterprise_banner'
|
||||
)
|
||||
|
||||
$scope.dismiss = () => {
|
||||
localStorage('has_dismissed_groups_and_enterprise_banner', true)
|
||||
$scope.hasDismissedGroupsAndEnterpriseBanner = true
|
||||
}
|
||||
|
||||
$scope.groupsAndEnterpriseBannerVariant = getMeta(
|
||||
'ol-groupsAndEnterpriseBannerVariant'
|
||||
)
|
||||
|
||||
const valid = ['did-you-know', 'on-premise', 'people', 'FOMO']
|
||||
|
||||
$scope.isVariantValid = valid.includes(
|
||||
$scope.groupsAndEnterpriseBannerVariant
|
||||
)
|
||||
|
||||
$scope.urlVariantSuffix = $scope.isVariantValid
|
||||
? `-${valid.indexOf($scope.groupsAndEnterpriseBannerVariant) + 1}`
|
||||
: ''
|
||||
}
|
||||
)
|
||||
|
||||
App.controller('ProjectInviteNotificationController', function ($scope, $http) {
|
||||
// Shortcuts for translation keys
|
||||
$scope.projectName = $scope.notification.messageOpts.projectName
|
||||
$scope.userName = $scope.notification.messageOpts.userName
|
||||
|
||||
$scope.accept = function () {
|
||||
$scope.notification.inflight = true
|
||||
return $http({
|
||||
url: `/project/${$scope.notification.messageOpts.projectId}/invite/token/${$scope.notification.messageOpts.token}/accept`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Csrf-Token': window.csrfToken,
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
$scope.notification.accepted = true
|
||||
})
|
||||
.catch(({ status }) => {
|
||||
if (status === 404) {
|
||||
// 404 probably means the invite has already been accepted and
|
||||
// deleted. Treat as success
|
||||
$scope.notification.accepted = true
|
||||
} else {
|
||||
$scope.notification.error = true
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
$scope.notification.inflight = false
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
App.controller(
|
||||
'EmailNotificationController',
|
||||
function ($scope, $http, UserAffiliationsDataService) {
|
||||
$scope.userEmails = window.data.userEmails
|
||||
const _ssoAvailable = email => {
|
||||
if (!ExposedSettings.hasSamlFeature) return false
|
||||
if (email.samlProviderId) return true
|
||||
if (!email.affiliation || !email.affiliation.institution) return false
|
||||
if (email.affiliation.institution.ssoEnabled) return true
|
||||
if (
|
||||
ExposedSettings.hasSamlBeta &&
|
||||
email.affiliation.institution.ssoBeta
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
$scope.showConfirmEmail = email => {
|
||||
if (ExposedSettings.emailConfirmationDisabled) {
|
||||
return false
|
||||
}
|
||||
if (!email.confirmedAt && !email.hide) {
|
||||
if (_ssoAvailable(email)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
for (const userEmail of $scope.userEmails) {
|
||||
userEmail.hide = false
|
||||
}
|
||||
|
||||
$scope.resendConfirmationEmail = function (userEmail) {
|
||||
userEmail.confirmationInflight = true
|
||||
userEmail.error = false
|
||||
userEmail.errorMessage = null
|
||||
UserAffiliationsDataService.resendConfirmationEmail(userEmail.email)
|
||||
.then(() => {
|
||||
userEmail.hide = true
|
||||
$scope.$emit('project-list:notifications-received')
|
||||
})
|
||||
.catch(error => {
|
||||
userEmail.error = true
|
||||
userEmail.errorMessage = error.data.message
|
||||
console.error(error)
|
||||
$scope.$emit('project-list:notifications-received')
|
||||
})
|
||||
.finally(() => {
|
||||
userEmail.confirmationInflight = false
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
|
@ -1,949 +0,0 @@
|
|||
import _ from 'lodash'
|
||||
import App from '../../base'
|
||||
import './services/project-list'
|
||||
import getMeta from '../../utils/meta'
|
||||
App.controller(
|
||||
'ProjectPageController',
|
||||
function (
|
||||
$scope,
|
||||
$modal,
|
||||
$window,
|
||||
queuedHttp,
|
||||
eventTracking, // eslint-disable-line camelcase
|
||||
$timeout,
|
||||
localStorage,
|
||||
ProjectListService
|
||||
) {
|
||||
$scope.projects = window.data.projects
|
||||
$scope.tags = window.data.tags
|
||||
$scope.notifications = window.data.notifications
|
||||
$scope.notificationsInstitution = window.data.notificationsInstitution
|
||||
$scope.allSelected = false
|
||||
$scope.selectedProjects = []
|
||||
$scope.filter = 'all'
|
||||
$scope.predicate = 'lastUpdated'
|
||||
$scope.nUntagged = 0
|
||||
$scope.reverse = true
|
||||
$scope.searchText = { value: '' }
|
||||
$scope.$watch('predicate', function (newValue) {
|
||||
$scope.comparator =
|
||||
newValue === 'ownerName' ? ownerNameComparator : defaultComparator
|
||||
})
|
||||
|
||||
const surveyName = getMeta('ol-survey-name')
|
||||
$scope.shouldShowSurveyLink =
|
||||
localStorage(`dismissed-${surveyName}`) !== true
|
||||
$scope.dismissSurvey = () => {
|
||||
localStorage(`dismissed-${surveyName}`, true)
|
||||
$scope.shouldShowSurveyLink = false
|
||||
}
|
||||
|
||||
$timeout(() => recalculateProjectListHeight(), 10)
|
||||
|
||||
$scope.$watch(
|
||||
() =>
|
||||
$scope.projects.filter(
|
||||
project =>
|
||||
(project.tags == null || project.tags.length === 0) &&
|
||||
!project.archived &&
|
||||
!project.trashed
|
||||
).length,
|
||||
newVal => ($scope.nUntagged = newVal)
|
||||
)
|
||||
|
||||
function recalculateProjectListHeight() {
|
||||
const $projListCard = $('.project-list-card')
|
||||
if (!$projListCard || !$projListCard.offset()) return
|
||||
|
||||
const topOffset = $projListCard.offset().top
|
||||
const cardPadding = $projListCard.outerHeight() - $projListCard.height()
|
||||
const bottomOffset = $('footer').outerHeight()
|
||||
const height =
|
||||
$window.innerHeight - topOffset - bottomOffset - cardPadding
|
||||
$scope.projectListHeight = height
|
||||
}
|
||||
|
||||
function defaultComparator(v1, v2) {
|
||||
let result = 0
|
||||
const type1 = v1.type
|
||||
const type2 = v2.type
|
||||
|
||||
if ($scope.predicate === 'ownerName') {
|
||||
return
|
||||
}
|
||||
|
||||
if (type1 === type2) {
|
||||
let value1 = v1.value
|
||||
let value2 = v2.value
|
||||
|
||||
if (type1 === 'string') {
|
||||
// Compare strings case-insensitively
|
||||
value1 = value1.toLowerCase()
|
||||
value2 = value2.toLowerCase()
|
||||
} else if (type1 === 'object') {
|
||||
// For basic objects, use the position of the object
|
||||
// in the collection instead of the value
|
||||
if (angular.isObject(value1)) value1 = v1.index
|
||||
if (angular.isObject(value2)) value2 = v2.index
|
||||
}
|
||||
|
||||
if (value1 !== value2) {
|
||||
result = value1 < value2 ? -1 : 1
|
||||
}
|
||||
} else {
|
||||
result = type1 < type2 ? -1 : 1
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function ownerNameComparator(v1, v2) {
|
||||
if ($scope.predicate !== 'ownerName') {
|
||||
return
|
||||
}
|
||||
if (v1.value === 'You') {
|
||||
if (v2.value === 'You') {
|
||||
return v1.index < v2.index ? -1 : 1
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
} else if (v1.value === 'An Overleaf v1 User' || v1.value === 'None') {
|
||||
if (v2.value === 'An Overleaf v1 User' || v2.value === 'None') {
|
||||
return v1.index < v2.index ? -1 : 1
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
} else {
|
||||
if (v2.value === 'You') {
|
||||
return -1
|
||||
} else if (v2.value === 'An Overleaf v1 User' || v2.value === 'None') {
|
||||
return 1
|
||||
} else {
|
||||
return v1.value > v2.value ? -1 : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.element($window).bind('resize', function () {
|
||||
recalculateProjectListHeight()
|
||||
$scope.$apply()
|
||||
})
|
||||
|
||||
$scope.$on('project-list:notifications-received', () =>
|
||||
$scope.$applyAsync(() => recalculateProjectListHeight())
|
||||
)
|
||||
|
||||
// Allow tags to be accessed on projects as well
|
||||
const projectsById = {}
|
||||
for (const project of $scope.projects) {
|
||||
projectsById[project.id] = project
|
||||
}
|
||||
|
||||
$scope.getProjectById = id => projectsById[id]
|
||||
|
||||
for (const tag of $scope.tags) {
|
||||
for (const projectId of tag.project_ids || []) {
|
||||
const project = projectsById[projectId]
|
||||
if (project) {
|
||||
if (!project.tags) {
|
||||
project.tags = []
|
||||
}
|
||||
project.tags.push(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope.changePredicate = function (newPredicate) {
|
||||
if ($scope.predicate === newPredicate) {
|
||||
$scope.reverse = !$scope.reverse
|
||||
}
|
||||
$scope.predicate = newPredicate
|
||||
}
|
||||
|
||||
$scope.getSortIconClass = function (column) {
|
||||
if (column === $scope.predicate && $scope.reverse) {
|
||||
return 'fa-caret-down'
|
||||
} else if (column === $scope.predicate && !$scope.reverse) {
|
||||
return 'fa-caret-up'
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
$scope.searchProjects = function () {
|
||||
eventTracking.send(
|
||||
'project-list-page-interaction',
|
||||
'project-search',
|
||||
'keydown'
|
||||
)
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.clearSearchText = function () {
|
||||
$scope.searchText.value = ''
|
||||
$scope.filter = 'all'
|
||||
$scope.$emit('search:clear')
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.setFilter = function (filter) {
|
||||
$scope.filter = filter
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.updateSelectedProjects = function () {
|
||||
$scope.selectedProjects = $scope.projects.filter(
|
||||
project => project.selected
|
||||
)
|
||||
}
|
||||
|
||||
$scope.getSelectedProjects = () => $scope.selectedProjects
|
||||
|
||||
$scope.getSelectedProjectIds = () =>
|
||||
$scope.selectedProjects.map(project => project.id)
|
||||
|
||||
$scope.getFirstSelectedProject = () => $scope.selectedProjects[0]
|
||||
|
||||
$scope.hasLeavableProjectsSelected = () =>
|
||||
_.some(
|
||||
$scope.getSelectedProjects(),
|
||||
project => project.accessLevel !== 'owner' && project.trashed
|
||||
)
|
||||
|
||||
$scope.hasDeletableProjectsSelected = () =>
|
||||
_.some(
|
||||
$scope.getSelectedProjects(),
|
||||
project => project.accessLevel === 'owner' && project.trashed
|
||||
)
|
||||
|
||||
$scope.updateVisibleProjects = function () {
|
||||
$scope.visibleProjects = []
|
||||
const selectedTag = $scope.getSelectedTag()
|
||||
for (const project of $scope.projects) {
|
||||
let visible = true
|
||||
// Only show if it matches any search text
|
||||
if ($scope.searchText.value !== '') {
|
||||
if (
|
||||
project.name
|
||||
.toLowerCase()
|
||||
.indexOf($scope.searchText.value.toLowerCase()) === -1
|
||||
) {
|
||||
visible = false
|
||||
}
|
||||
}
|
||||
// Only show if it matches the selected tag
|
||||
if (
|
||||
$scope.filter === 'tag' &&
|
||||
selectedTag != null &&
|
||||
!selectedTag.project_ids.includes(project.id)
|
||||
) {
|
||||
visible = false
|
||||
}
|
||||
|
||||
// Hide tagged projects if we only want to see the uncategorized ones
|
||||
if (
|
||||
$scope.filter === 'untagged' &&
|
||||
(project.tags != null ? project.tags.length : undefined) > 0
|
||||
) {
|
||||
visible = false
|
||||
}
|
||||
|
||||
// Hide projects we own if we only want to see shared projects
|
||||
if ($scope.filter === 'shared' && project.accessLevel === 'owner') {
|
||||
visible = false
|
||||
}
|
||||
|
||||
// Hide projects we don't own if we only want to see owned projects
|
||||
if ($scope.filter === 'owned' && project.accessLevel !== 'owner') {
|
||||
visible = false
|
||||
}
|
||||
|
||||
if ($scope.filter === 'archived') {
|
||||
// Only show archived projects
|
||||
if (!project.archived) {
|
||||
visible = false
|
||||
}
|
||||
} else {
|
||||
// Only show non-archived projects
|
||||
if (project.archived) {
|
||||
visible = false
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope.filter === 'trashed') {
|
||||
// Only show trashed projects
|
||||
if (!project.trashed) {
|
||||
visible = false
|
||||
}
|
||||
} else {
|
||||
// Only show non-trashed projects
|
||||
if (project.trashed) {
|
||||
visible = false
|
||||
}
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
$scope.visibleProjects.push(project)
|
||||
} else {
|
||||
// We don't want hidden selections
|
||||
project.selected = false
|
||||
}
|
||||
}
|
||||
|
||||
localStorage(
|
||||
'project_list',
|
||||
JSON.stringify({
|
||||
filter: $scope.filter,
|
||||
selectedTagId: selectedTag != null ? selectedTag._id : undefined,
|
||||
})
|
||||
)
|
||||
$scope.updateSelectedProjects()
|
||||
}
|
||||
|
||||
$scope.getSelectedTag = function () {
|
||||
for (const tag of $scope.tags) {
|
||||
if (tag.selected) {
|
||||
return tag
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
$scope._removeProjectIdsFromTagArray = function (tag, removeProjectIds) {
|
||||
// Remove project_id from tag.project_ids
|
||||
const remainingProjectIds = []
|
||||
const removedProjectIds = []
|
||||
for (const projectId of tag.project_ids) {
|
||||
if (!removeProjectIds.includes(projectId)) {
|
||||
remainingProjectIds.push(projectId)
|
||||
} else {
|
||||
removedProjectIds.push(projectId)
|
||||
}
|
||||
}
|
||||
tag.project_ids = remainingProjectIds
|
||||
return removedProjectIds
|
||||
}
|
||||
|
||||
$scope._removeProjectFromList = function (project) {
|
||||
const index = $scope.projects.indexOf(project)
|
||||
if (index > -1) {
|
||||
$scope.projects.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
$scope.removeSelectedProjectsFromTag = function (tag) {
|
||||
tag.showWhenEmpty = true
|
||||
|
||||
const selectedProjectIds = $scope.getSelectedProjectIds()
|
||||
const selectedProjects = $scope.getSelectedProjects()
|
||||
|
||||
const removedProjectIds = $scope._removeProjectIdsFromTagArray(
|
||||
tag,
|
||||
selectedProjectIds
|
||||
)
|
||||
|
||||
// Remove tag from project.tags
|
||||
for (const project of selectedProjects) {
|
||||
if (!project.tags) {
|
||||
project.tags = []
|
||||
}
|
||||
const index = project.tags.indexOf(tag)
|
||||
if (index > -1) {
|
||||
project.tags.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
for (const projectId of removedProjectIds) {
|
||||
queuedHttp({
|
||||
method: 'DELETE',
|
||||
url: `/tag/${tag._id}/project/${projectId}`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// If we're filtering by this tag then we need to remove
|
||||
// the projects from view
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.removeProjectFromTag = function (project, tag) {
|
||||
tag.showWhenEmpty = true
|
||||
|
||||
if (!project.tags) {
|
||||
project.tags = []
|
||||
}
|
||||
const index = project.tags.indexOf(tag)
|
||||
|
||||
if (index > -1) {
|
||||
$scope._removeProjectIdsFromTagArray(tag, [project.id])
|
||||
project.tags.splice(index, 1)
|
||||
queuedHttp({
|
||||
method: 'DELETE',
|
||||
url: `/tag/${tag._id}/project/${project.id}`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
}
|
||||
|
||||
$scope.addSelectedProjectsToTag = function (tag) {
|
||||
const selectedProjects = $scope.getSelectedProjects()
|
||||
eventTracking.send(
|
||||
'project-list-page-interaction',
|
||||
'project action',
|
||||
'addSelectedProjectsToTag'
|
||||
)
|
||||
|
||||
// Add project_ids into tag.project_ids
|
||||
const addedProjectIds = []
|
||||
for (const projectId of $scope.getSelectedProjectIds()) {
|
||||
if (!tag.project_ids.includes(projectId)) {
|
||||
tag.project_ids.push(projectId)
|
||||
addedProjectIds.push(projectId)
|
||||
}
|
||||
}
|
||||
|
||||
// Add tag into each project.tags
|
||||
for (const project of selectedProjects) {
|
||||
if (!project.tags) {
|
||||
project.tags = []
|
||||
}
|
||||
if (!project.tags.includes(tag)) {
|
||||
project.tags.push(tag)
|
||||
}
|
||||
}
|
||||
|
||||
for (const projectId of addedProjectIds) {
|
||||
queuedHttp.post(`/tag/${tag._id}/project/${projectId}`, {
|
||||
_csrf: window.csrfToken,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$scope.openNewTagModal = function (e) {
|
||||
const modalInstance = $modal.open({
|
||||
templateUrl: 'newTagModalTemplate',
|
||||
controller: 'NewTagModalController',
|
||||
})
|
||||
|
||||
modalInstance.result.then(function (tag) {
|
||||
const tagIsDuplicate = $scope.tags.find(function (existingTag) {
|
||||
return tag.name === existingTag.name
|
||||
})
|
||||
|
||||
if (!tagIsDuplicate) {
|
||||
$scope.tags.push(tag)
|
||||
$scope.addSelectedProjectsToTag(tag)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$scope.createProject = function (name, template) {
|
||||
if (template == null) {
|
||||
template = 'none'
|
||||
}
|
||||
return queuedHttp
|
||||
.post('/project/new', {
|
||||
_csrf: window.csrfToken,
|
||||
projectName: name,
|
||||
template,
|
||||
})
|
||||
.then(function (response) {
|
||||
const { data } = response
|
||||
$scope.projects.push({
|
||||
name,
|
||||
id: data.project_id,
|
||||
accessLevel: 'owner',
|
||||
owner: data.owner,
|
||||
// TODO: Check access level if correct after adding it in
|
||||
// to the rest of the app
|
||||
})
|
||||
$scope.updateVisibleProjects()
|
||||
})
|
||||
}
|
||||
|
||||
$scope.openCreateProjectModal = function (template) {
|
||||
if (template == null) {
|
||||
template = 'none'
|
||||
}
|
||||
eventTracking.send(
|
||||
'project-list-page-interaction',
|
||||
'new-project',
|
||||
template
|
||||
)
|
||||
const modalInstance = $modal.open({
|
||||
templateUrl: 'newProjectModalTemplate',
|
||||
controller: 'NewProjectModalController',
|
||||
resolve: {
|
||||
template() {
|
||||
return template
|
||||
},
|
||||
},
|
||||
scope: $scope,
|
||||
})
|
||||
|
||||
modalInstance.result.then(
|
||||
projectId => (window.location = `/project/${projectId}`)
|
||||
)
|
||||
}
|
||||
|
||||
$scope.renameProject = (project, newName) =>
|
||||
queuedHttp
|
||||
.post(`/project/${project.id}/rename`, {
|
||||
newProjectName: newName,
|
||||
_csrf: window.csrfToken,
|
||||
})
|
||||
.then(() => (project.name = newName))
|
||||
|
||||
$scope.openRenameProjectModal = function () {
|
||||
const project = $scope.getFirstSelectedProject()
|
||||
if (!project || project.accessLevel !== 'owner') {
|
||||
return
|
||||
}
|
||||
eventTracking.send(
|
||||
'project-list-page-interaction',
|
||||
'project action',
|
||||
'Rename'
|
||||
)
|
||||
$modal.open({
|
||||
templateUrl: 'renameProjectModalTemplate',
|
||||
controller: 'RenameProjectModalController',
|
||||
resolve: {
|
||||
project() {
|
||||
return project
|
||||
},
|
||||
},
|
||||
scope: $scope,
|
||||
})
|
||||
}
|
||||
|
||||
$scope.cloneProject = function (project, cloneName) {
|
||||
eventTracking.send(
|
||||
'project-list-page-interaction',
|
||||
'project action',
|
||||
'Clone'
|
||||
)
|
||||
return queuedHttp
|
||||
.post(`/project/${project.id}/clone`, {
|
||||
_csrf: window.csrfToken,
|
||||
projectName: cloneName,
|
||||
})
|
||||
.then(function (response) {
|
||||
const { data } = response
|
||||
$scope.projects.push({
|
||||
name: data.name,
|
||||
id: data.project_id,
|
||||
accessLevel: 'owner',
|
||||
owner: data.owner,
|
||||
// TODO: Check access level if correct after adding it in
|
||||
// to the rest of the app
|
||||
})
|
||||
$scope.updateVisibleProjects()
|
||||
})
|
||||
}
|
||||
|
||||
$scope.openCloneProjectModal = function (project) {
|
||||
if (!project) {
|
||||
return
|
||||
}
|
||||
|
||||
$modal.open({
|
||||
templateUrl: 'cloneProjectModalTemplate',
|
||||
controller: 'CloneProjectModalController',
|
||||
resolve: {
|
||||
project() {
|
||||
return project
|
||||
},
|
||||
},
|
||||
scope: $scope,
|
||||
})
|
||||
}
|
||||
|
||||
// Methods to create modals for archiving, trashing, leaving and deleting projects
|
||||
const _createArchiveTrashLeaveOrDeleteProjectsModal = function (
|
||||
action,
|
||||
projects
|
||||
) {
|
||||
eventTracking.send(
|
||||
'project-list-page-interaction',
|
||||
'project action',
|
||||
action
|
||||
)
|
||||
return $modal.open({
|
||||
templateUrl: 'archiveTrashLeaveOrDeleteProjectsModalTemplate',
|
||||
controller: 'ArchiveTrashLeaveOrDeleteProjectsModalController',
|
||||
resolve: {
|
||||
projects() {
|
||||
return projects
|
||||
},
|
||||
action() {
|
||||
return action
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
$scope.createArchiveProjectsModal = function (projects) {
|
||||
return _createArchiveTrashLeaveOrDeleteProjectsModal('archive', projects)
|
||||
}
|
||||
|
||||
$scope.createTrashProjectsModal = function (projects) {
|
||||
return _createArchiveTrashLeaveOrDeleteProjectsModal('trash', projects)
|
||||
}
|
||||
|
||||
$scope.createLeaveProjectsModal = function (projects) {
|
||||
return _createArchiveTrashLeaveOrDeleteProjectsModal('leave', projects)
|
||||
}
|
||||
|
||||
$scope.createDeleteProjectsModal = function (projects) {
|
||||
return _createArchiveTrashLeaveOrDeleteProjectsModal('delete', projects)
|
||||
}
|
||||
|
||||
$scope.createLeaveOrDeleteProjectsModal = function (projects) {
|
||||
return _createArchiveTrashLeaveOrDeleteProjectsModal(
|
||||
'leaveOrDelete',
|
||||
projects
|
||||
)
|
||||
}
|
||||
|
||||
//
|
||||
$scope.openArchiveProjectsModal = function () {
|
||||
const modalInstance = $scope.createArchiveProjectsModal(
|
||||
$scope.getSelectedProjects()
|
||||
)
|
||||
modalInstance.result.then(() => $scope.archiveSelectedProjects())
|
||||
}
|
||||
|
||||
$scope.openTrashProjectsModal = function () {
|
||||
const modalInstance = $scope.createTrashProjectsModal(
|
||||
$scope.getSelectedProjects()
|
||||
)
|
||||
|
||||
modalInstance.result.then(() => $scope.trashSelectedProjects())
|
||||
}
|
||||
|
||||
$scope.openLeaveProjectsModal = function () {
|
||||
const modalInstance = $scope.createLeaveProjectsModal(
|
||||
$scope.getSelectedProjects()
|
||||
)
|
||||
modalInstance.result.then(() => $scope.leaveSelectedProjects())
|
||||
}
|
||||
|
||||
$scope.openDeleteProjectsModal = function () {
|
||||
const modalInstance = $scope.createDeleteProjectsModal(
|
||||
$scope.getSelectedProjects()
|
||||
)
|
||||
modalInstance.result.then(() => $scope.deleteSelectedProjects())
|
||||
}
|
||||
|
||||
$scope.openLeaveOrDeleteProjectsModal = function () {
|
||||
const modalInstance = $scope.createLeaveOrDeleteProjectsModal(
|
||||
$scope.getSelectedProjects()
|
||||
)
|
||||
modalInstance.result.then(() => $scope.leaveOrDeleteSelectedProjects())
|
||||
}
|
||||
|
||||
//
|
||||
$scope.archiveSelectedProjects = () =>
|
||||
$scope.archiveProjects($scope.getSelectedProjects())
|
||||
|
||||
$scope.unarchiveSelectedProjects = () =>
|
||||
$scope.unarchiveProjects($scope.getSelectedProjects())
|
||||
|
||||
$scope.trashSelectedProjects = () =>
|
||||
$scope.trashProjects($scope.getSelectedProjects())
|
||||
|
||||
$scope.untrashSelectedProjects = () =>
|
||||
$scope.untrashProjects($scope.getSelectedProjects())
|
||||
|
||||
$scope.leaveSelectedProjects = () =>
|
||||
$scope.leaveProjects($scope.getSelectedProjects())
|
||||
|
||||
$scope.deleteSelectedProjects = () =>
|
||||
$scope.deleteProjects($scope.getSelectedProjects())
|
||||
|
||||
$scope.leaveOrDeleteSelectedProjects = () =>
|
||||
$scope.leaveOrDeleteProjects($scope.getSelectedProjects())
|
||||
|
||||
//
|
||||
$scope.archiveProjects = function (projects) {
|
||||
for (const project of projects) {
|
||||
project.archived = true
|
||||
project.trashed = false
|
||||
_archiveProject(project)
|
||||
}
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.unarchiveProjects = function (projects) {
|
||||
for (const project of projects) {
|
||||
project.archived = false
|
||||
_unarchiveProject(project)
|
||||
}
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.trashProjects = function (projects) {
|
||||
for (const project of projects) {
|
||||
project.trashed = true
|
||||
project.archived = false
|
||||
_trashProject(project)
|
||||
}
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.untrashProjects = function (projects) {
|
||||
for (const project of projects) {
|
||||
project.trashed = false
|
||||
_untrashProject(project)
|
||||
}
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.leaveProjects = function (projects) {
|
||||
_deleteOrLeaveProjectsLocally(projects)
|
||||
for (const project of projects) {
|
||||
_leaveProject(project)
|
||||
}
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.deleteProjects = function (projects) {
|
||||
_deleteOrLeaveProjectsLocally(projects)
|
||||
for (const project of projects) {
|
||||
_deleteProject(project)
|
||||
}
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
$scope.leaveOrDeleteProjects = function (projects) {
|
||||
_deleteOrLeaveProjectsLocally(projects)
|
||||
for (const project of projects) {
|
||||
if (project.accessLevel === 'owner') {
|
||||
_deleteProject(project)
|
||||
} else {
|
||||
_leaveProject(project)
|
||||
}
|
||||
}
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
|
||||
// Actual interaction with the backend---we could move this into a service
|
||||
const _archiveProject = function (project) {
|
||||
return queuedHttp({
|
||||
method: 'POST',
|
||||
url: `/project/${project.id}/archive`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const _unarchiveProject = function (project) {
|
||||
return queuedHttp({
|
||||
method: 'DELETE',
|
||||
url: `/project/${project.id}/archive`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const _trashProject = function (project) {
|
||||
return queuedHttp({
|
||||
method: 'POST',
|
||||
url: `/project/${project.id}/trash`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const _untrashProject = function (project) {
|
||||
return queuedHttp({
|
||||
method: 'DELETE',
|
||||
url: `/project/${project.id}/trash`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const _leaveProject = function (project) {
|
||||
return queuedHttp({
|
||||
method: 'POST',
|
||||
url: `/project/${project.id}/leave`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const _deleteProject = function (project) {
|
||||
return queuedHttp({
|
||||
method: 'DELETE',
|
||||
url: `/project/${project.id}`,
|
||||
headers: {
|
||||
'X-CSRF-Token': window.csrfToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const _deleteOrLeaveProjectsLocally = function (projects) {
|
||||
const projectIds = projects.map(p => p.id)
|
||||
for (const tag of $scope.tags || []) {
|
||||
$scope._removeProjectIdsFromTagArray(tag, projectIds)
|
||||
}
|
||||
for (const project of projects || []) {
|
||||
$scope._removeProjectFromList(project)
|
||||
}
|
||||
}
|
||||
|
||||
$scope.getValueForCurrentPredicate = function (project) {
|
||||
if ($scope.predicate === 'ownerName') {
|
||||
return ProjectListService.getOwnerName(project)
|
||||
} else {
|
||||
return project[$scope.predicate]
|
||||
}
|
||||
}
|
||||
|
||||
$scope.openUploadProjectModal = function () {
|
||||
$modal.open({
|
||||
templateUrl: 'uploadProjectModalTemplate',
|
||||
controller: 'UploadProjectModalController',
|
||||
})
|
||||
}
|
||||
|
||||
$scope.downloadSelectedProjects = () =>
|
||||
$scope.downloadProjectsById($scope.getSelectedProjectIds())
|
||||
|
||||
$scope.sendUpgradeButtonClickEvent = () => {
|
||||
eventTracking.sendMB('upgrade-button-click', {
|
||||
source: 'dashboard-top',
|
||||
'project-dashboard-react': 'default',
|
||||
'is-dashboard-sidebar-hidden': false,
|
||||
'is-screen-width-less-than-768px':
|
||||
window.matchMedia('(max-width: 767px)').matches,
|
||||
})
|
||||
}
|
||||
|
||||
$scope.downloadProjectsById = function (projectIds) {
|
||||
let path
|
||||
eventTracking.send(
|
||||
'project-list-page-interaction',
|
||||
'project action',
|
||||
'Download Zip'
|
||||
)
|
||||
if (projectIds.length > 1) {
|
||||
path = `/project/download/zip?project_ids=${projectIds.join(',')}`
|
||||
} else {
|
||||
path = `/project/${projectIds[0]}/download/zip`
|
||||
}
|
||||
return (window.location = path)
|
||||
}
|
||||
|
||||
const markTagAsSelected = id => {
|
||||
for (const tag of $scope.tags) {
|
||||
if (tag._id === id) {
|
||||
tag.selected = true
|
||||
} else {
|
||||
tag.selected = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const storedUIOpts = JSON.parse(localStorage('project_list'))
|
||||
|
||||
if (storedUIOpts && storedUIOpts.filter) {
|
||||
if (storedUIOpts.filter === 'tag' && storedUIOpts.selectedTagId) {
|
||||
markTagAsSelected(storedUIOpts.selectedTagId)
|
||||
}
|
||||
$scope.setFilter(storedUIOpts.filter)
|
||||
} else {
|
||||
$scope.updateVisibleProjects()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
App.controller(
|
||||
'ProjectListItemController',
|
||||
function ($scope, $modal, queuedHttp, ProjectListService) {
|
||||
$scope.projectLink = function (project) {
|
||||
return `/project/${project.id}`
|
||||
}
|
||||
|
||||
$scope.isLinkSharingProject = project => project.source === 'token'
|
||||
|
||||
$scope.hasGenericOwnerName = () => {
|
||||
/* eslint-disable camelcase */
|
||||
const { first_name, last_name, email } = $scope.project.owner
|
||||
return !first_name && !last_name && !email
|
||||
/* eslint-enable camelcase */
|
||||
}
|
||||
|
||||
$scope.getOwnerName = ProjectListService.getOwnerName
|
||||
|
||||
$scope.getUserName = ProjectListService.getUserName
|
||||
|
||||
$scope.isOwner = () =>
|
||||
$scope.project.owner && window.user_id === $scope.project.owner._id
|
||||
|
||||
$scope.$watch('project.selected', function (value) {
|
||||
if (value != null) {
|
||||
$scope.updateSelectedProjects()
|
||||
}
|
||||
})
|
||||
|
||||
$scope.clone = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.openCloneProjectModal($scope.project)
|
||||
}
|
||||
|
||||
$scope.download = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.downloadProjectsById([$scope.project.id])
|
||||
}
|
||||
|
||||
$scope.archive = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.createArchiveProjectsModal([$scope.project]).result.then(() => {
|
||||
$scope.archiveProjects([$scope.project])
|
||||
})
|
||||
}
|
||||
|
||||
$scope.unarchive = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.unarchiveProjects([$scope.project])
|
||||
}
|
||||
|
||||
$scope.trash = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.createTrashProjectsModal([$scope.project]).result.then(() => {
|
||||
$scope.trashProjects([$scope.project])
|
||||
})
|
||||
}
|
||||
|
||||
$scope.untrash = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.untrashProjects([$scope.project])
|
||||
}
|
||||
|
||||
$scope.leave = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.createLeaveProjectsModal([$scope.project]).result.then(() => {
|
||||
$scope.leaveProjects([$scope.project])
|
||||
})
|
||||
}
|
||||
|
||||
$scope.delete = function (e) {
|
||||
e.stopPropagation()
|
||||
$scope.createDeleteProjectsModal([$scope.project]).result.then(() => {
|
||||
$scope.deleteProjects([$scope.project])
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
|
@ -1,35 +0,0 @@
|
|||
/* eslint-disable
|
||||
camelcase
|
||||
*/
|
||||
import App from '../../../base'
|
||||
|
||||
export default App.service('ProjectListService', function () {
|
||||
return {
|
||||
getOwnerName(project) {
|
||||
if (project.accessLevel === 'owner') {
|
||||
return 'You'
|
||||
} else if (project.owner != null) {
|
||||
return this.getUserName(project.owner)
|
||||
} else {
|
||||
return 'None'
|
||||
}
|
||||
},
|
||||
|
||||
getUserName(user) {
|
||||
if (user && user._id === window.user_id) {
|
||||
return 'You'
|
||||
} else if (user) {
|
||||
const { first_name, last_name, email } = user
|
||||
if (first_name || last_name) {
|
||||
return [first_name, last_name].filter(n => n != null).join(' ')
|
||||
} else if (email) {
|
||||
return email
|
||||
} else {
|
||||
return 'An Overleaf v1 User'
|
||||
}
|
||||
} else {
|
||||
return 'None'
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
|
@ -11,7 +11,6 @@
|
|||
"add": "Přidat",
|
||||
"add_more_members": "Přidat více členů",
|
||||
"add_to_folder": "Přidat do složky",
|
||||
"add_to_folders": "Přidat do složek",
|
||||
"add_your_first_group_member_now": "Přidejte do vaší skupiny prvního člena",
|
||||
"added": "přidáno",
|
||||
"admin": "administrátor",
|
||||
|
@ -77,7 +76,6 @@
|
|||
"create_new_folder": "Vytvořit novou složku",
|
||||
"create_new_subscription": "Vytvořit nové předplatné.",
|
||||
"create_project_in_github": "Vytvořit GitHub repozitář.",
|
||||
"create_your_first_project": "Vytvořte svůj první projekt!",
|
||||
"creating": "Vytvářím",
|
||||
"cs": "Čeština",
|
||||
"current_password": "Aktuální heslo",
|
||||
|
@ -220,7 +218,6 @@
|
|||
"online_latex_editor": "Online LaTeX editor",
|
||||
"optional": "Dobrovolný",
|
||||
"or": "nebo",
|
||||
"or_create_project_left": "nebo nalevo vytvořit váš prví projekt.",
|
||||
"other_logs_and_files": "Ostatní logy a soubory",
|
||||
"over": "více než",
|
||||
"over_x_templates_easy_getting_started": "V naší galerii naleznete tísíce __templates__, takže he opravdu jednoduché začít, ať už chcete psát článek do časopisu, závěrečnou práci, CV, nebo něco jiného.",
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
"add_or_remove_project_from_tag": "Føj projekt til, eller fjern projekt fra, tagget __tagName__",
|
||||
"add_role_and_department": "Tilføj rolle og afdeling",
|
||||
"add_to_folder": "Tilføj til mappe",
|
||||
"add_to_folders": "Tilføj til mapper",
|
||||
"add_your_comment_here": "Tilføj din kommentar her",
|
||||
"add_your_first_group_member_now": "Tilføj de første medlemmer til din gruppe nu",
|
||||
"added": "tilføjet",
|
||||
|
@ -238,7 +237,6 @@
|
|||
"create_new_folder": "Opret ny mappe",
|
||||
"create_new_subscription": "Lav nyt abonnement",
|
||||
"create_project_in_github": "Skab et GitHub lager",
|
||||
"create_your_first_project": "Lav dit første projekt!",
|
||||
"created_at": "Oprettet",
|
||||
"creating": "Opretter",
|
||||
"credit_card": "Kredit kort",
|
||||
|
@ -703,7 +701,6 @@
|
|||
"opted_out_linking": "Du har fravalgt at forbinde din <b>__appName__</b>–konto for <b>__email__</b> til din institutionelle konto.",
|
||||
"optional": "Valgfrit",
|
||||
"or": "eller",
|
||||
"or_create_project_left": "eller opret dit første projekt til venstre.",
|
||||
"other_actions": "Andre handlinger",
|
||||
"other_logs_and_files": "Andre logger og filer",
|
||||
"other_output_files": "Hent andre udfiler",
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
"add_new_email": "Neue E-Mail-Adresse hinzufügen",
|
||||
"add_role_and_department": "Rolle und Abteilung hinzufügen",
|
||||
"add_to_folder": "Zu Ordner hinzufügen",
|
||||
"add_to_folders": "Zu Ordnern hinzufügen",
|
||||
"add_your_comment_here": "Füge hier einen Kommentar hinzu",
|
||||
"add_your_first_group_member_now": "Füge jetzt dein erstes Gruppenmitglied hinzu",
|
||||
"added": "hinzugefügt",
|
||||
|
@ -251,7 +250,6 @@
|
|||
"create_new_folder": "Neuen Ordner erstellen",
|
||||
"create_new_subscription": "Neues Abonnement erstellen",
|
||||
"create_project_in_github": "Ein GitHub Repository erstellen",
|
||||
"create_your_first_project": "Erstelle dein erstes Projekt!",
|
||||
"creating": "Erstellung läuft",
|
||||
"credit_card": "Kreditkarte",
|
||||
"cs": "Tschechisch",
|
||||
|
@ -851,7 +849,6 @@
|
|||
"opted_out_linking": "Du hast dich gegen die Verknüpfung deines <b>__email__</b> <b>__appName__</b>-Kontos mit deinem institutionellen Konto entschieden.",
|
||||
"optional": "Freiwillig",
|
||||
"or": "oder",
|
||||
"or_create_project_left": "oder erstelle dein erstes Projekt auf der linken Seite.",
|
||||
"organization": "Organisation",
|
||||
"other_actions": "Weitere Aktionen",
|
||||
"other_logs_and_files": "Andere Protokolle und Dateien",
|
||||
|
|
|
@ -60,8 +60,6 @@
|
|||
"add_new_email": "Add new email",
|
||||
"add_or_remove_project_from_tag": "Add or remove project from tag __tagName__",
|
||||
"add_role_and_department": "Add role and department",
|
||||
"add_to_folder": "Add to folder",
|
||||
"add_to_folders": "Add to folders",
|
||||
"add_to_tag": "Add to tag",
|
||||
"add_your_comment_here": "Add your comment here",
|
||||
"add_your_first_group_member_now": "Add your first group members now",
|
||||
|
@ -301,8 +299,6 @@
|
|||
"create_new_subscription": "Create New Subscription",
|
||||
"create_new_tag": "Create new tag",
|
||||
"create_project_in_github": "Create a GitHub repository",
|
||||
"create_your_first_project": "Create your first project!",
|
||||
"created": "created",
|
||||
"created_at": "Created at",
|
||||
"creating": "Creating",
|
||||
"credit_card": "Credit Card",
|
||||
|
@ -927,7 +923,6 @@
|
|||
"main_file_not_found": "Unknown main document",
|
||||
"maintenance": "Maintenance",
|
||||
"make_a_copy": "Make a copy",
|
||||
"make_copy": "Make a copy",
|
||||
"make_email_primary_description": "Make this the primary email, used to log in",
|
||||
"make_primary": "Make Primary",
|
||||
"make_private": "Make Private",
|
||||
|
@ -1079,7 +1074,6 @@
|
|||
"opted_out_linking": "You’ve opted out from linking your <b>__email__</b> <b>__appName__</b> account to your institutional account.",
|
||||
"optional": "Optional",
|
||||
"or": "or",
|
||||
"or_create_project_left": "or create your first project on the left.",
|
||||
"organization": "Organization",
|
||||
"organization_type": "Organization Type",
|
||||
"organize_projects": "Organize Projects",
|
||||
|
@ -1530,7 +1524,6 @@
|
|||
"tagline_student_annual": "Save even more",
|
||||
"tagline_student_monthly": "Great for a single term",
|
||||
"tags": "Tags",
|
||||
"tags_slash_folders": "Tags/Folders",
|
||||
"take_me_home": "Take me home!",
|
||||
"take_short_survey": "Take a short survey",
|
||||
"tc_everyone": "Everyone",
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
"add": "Agregar",
|
||||
"add_more_members": "Agregar más miembros",
|
||||
"add_to_folder": "Agrega a una carpeta",
|
||||
"add_to_folders": "Agregar a carpetas",
|
||||
"add_your_first_group_member_now": "Agrega tu primer grupo de miembros ahora",
|
||||
"added": "agregado",
|
||||
"adding": "Añadiendo",
|
||||
|
@ -103,7 +102,6 @@
|
|||
"create_new_folder": "Crear nueva carpeta",
|
||||
"create_new_subscription": "Crear nueva suscripción",
|
||||
"create_project_in_github": "Crear un repositorio en GitHub",
|
||||
"create_your_first_project": "¡Crea tu primer proyecto!",
|
||||
"creating": "Creando",
|
||||
"credit_card": "Tarjeta de crédito",
|
||||
"cs": "Checo",
|
||||
|
@ -290,7 +288,6 @@
|
|||
"open_a_file_on_the_left": "Abrir un archivo a la izquierda",
|
||||
"optional": "Opcional",
|
||||
"or": "o",
|
||||
"or_create_project_left": "o crea tu primer proyecto a la izquierda.",
|
||||
"other_logs_and_files": "Otros logs y archivos",
|
||||
"over": "más",
|
||||
"over_x_templates_easy_getting_started": "Hay __over__ de 400 __templates__ en nuestra galería de plantillas, así que es bastante fácil empezar, ya sea que estés escribiendo un artículo científico, una tesis, un CV u otro.",
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
"add": "Lisää",
|
||||
"add_more_members": "Lisää jäseniä",
|
||||
"add_to_folder": "Lisää kansioon",
|
||||
"add_to_folders": "Lisää kansioihin",
|
||||
"add_your_first_group_member_now": "Lisää ensimmäiset ryhmäsi jäsenet nyt",
|
||||
"added": "lisätty",
|
||||
"address": "Osoite",
|
||||
|
@ -79,7 +78,6 @@
|
|||
"create_new_folder": "Luo uusi kansio",
|
||||
"create_new_subscription": "Luo uusi tilaus",
|
||||
"create_project_in_github": "Luo GitHub-repository",
|
||||
"create_your_first_project": "Luo ensimmäinen projektisi!",
|
||||
"creating": "Luodaan",
|
||||
"credit_card": "Luottokortti",
|
||||
"cs": "Tsekki",
|
||||
|
@ -229,7 +227,6 @@
|
|||
"online_latex_editor": "Verkossa toimiva LaTeX-editori",
|
||||
"optional": "Valinnainen",
|
||||
"or": "tai",
|
||||
"or_create_project_left": "tai luo ensimmäinen projekti vasemmalta.",
|
||||
"other_logs_and_files": "Muut lokit & tiedostot",
|
||||
"over": "yli",
|
||||
"over_x_templates_easy_getting_started": "Mallipohjagalleriastamme löytyy __yli__ 400 __mallipohjaa__, joten pääset todella helposti alkuun, kirjoitit sitten tiedeartikkelia, väitöstä, ansioluetteloa tai jotain muuta.",
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
"add_new_email": "Ajouter l’adresse",
|
||||
"add_role_and_department": "Ajouter votre rôle et votre département",
|
||||
"add_to_folder": "Ajouter au dossier",
|
||||
"add_to_folders": "Ajouter aux dossiers",
|
||||
"add_your_comment_here": "Ajoutez votre commentaire ici",
|
||||
"add_your_first_group_member_now": "Ajouter le premier membre de votre groupe maintenant",
|
||||
"added": "ajouté",
|
||||
|
@ -228,7 +227,6 @@
|
|||
"create_new_folder": "Créer un nouveau dossier",
|
||||
"create_new_subscription": "Créer un nouvel abonnement",
|
||||
"create_project_in_github": "Créer un dépôt GitHub",
|
||||
"create_your_first_project": "Créer votre premier projet !",
|
||||
"creating": "Création en cours",
|
||||
"credit_card": "Carte bleue",
|
||||
"cs": "Tchéque",
|
||||
|
@ -703,7 +701,6 @@
|
|||
"opted_out_linking": "Vous avez choisi de ne pas lier votre compte <b>__appName__</b> <b>__email__</b> à votre compte institutionnel.",
|
||||
"optional": "Optionnel",
|
||||
"or": "ou",
|
||||
"or_create_project_left": "ou créez votre premier projet à gauche.",
|
||||
"other_actions": "Autres actions",
|
||||
"other_logs_and_files": "Autres journaux et fichiers",
|
||||
"other_output_files": "Télécharger les autres fichiers générés",
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
"add": "Aggiungi",
|
||||
"add_more_members": "Aggiungi membri",
|
||||
"add_to_folder": "Aggiungi a cartella",
|
||||
"add_to_folders": "Aggiungi a cartelle",
|
||||
"add_your_first_group_member_now": "Aggiungi ora i primi membri del gruppo",
|
||||
"added": "aggiunto",
|
||||
"adding": "Aggiunta",
|
||||
|
@ -93,7 +92,6 @@
|
|||
"create_new_folder": "Crea Nuova Cartella",
|
||||
"create_new_subscription": "Crea Nuovo Abbonamento",
|
||||
"create_project_in_github": "Crea un repository GitHub",
|
||||
"create_your_first_project": "Crea il tuo primo progetto!",
|
||||
"creating": "Creazione",
|
||||
"credit_card": "Carta di Credito",
|
||||
"cs": "Ceco",
|
||||
|
@ -256,7 +254,6 @@
|
|||
"online_latex_editor": "Editor LaTeX online",
|
||||
"optional": "Opzionale",
|
||||
"or": "o",
|
||||
"or_create_project_left": "o crea il tuo primo progetto a sinistra.",
|
||||
"other_logs_and_files": "Altri log & file",
|
||||
"over": "su",
|
||||
"over_x_templates_easy_getting_started": "Esistono __over__ 400 __templates__ nella nostra galleria di modelli, ed è quindi molto facile iniziare, sia che tu stia scrivendo un articolo, una tesi, un CV o qualcos altro.",
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
"add": "追加",
|
||||
"add_more_members": "メンバーの追加",
|
||||
"add_to_folder": "フォルダに追加",
|
||||
"add_to_folders": "フォルダに追加",
|
||||
"add_your_first_group_member_now": "最初のグループメンバーを今すぐ追加",
|
||||
"added": "追加",
|
||||
"adding": "追加中",
|
||||
|
@ -120,7 +119,6 @@
|
|||
"create_new_folder": "新規フォルダの作成",
|
||||
"create_new_subscription": "新しい購読の作成",
|
||||
"create_project_in_github": "GitHubリポジトリの作成",
|
||||
"create_your_first_project": "最初のプロジェクトを作成!",
|
||||
"creating": "作成中",
|
||||
"credit_card": "クレジットカード",
|
||||
"cs": "チェコ語",
|
||||
|
@ -335,7 +333,6 @@
|
|||
"open_project": "プロジェクトを開く",
|
||||
"optional": "オプショナル",
|
||||
"or": "または",
|
||||
"or_create_project_left": "あるいは、左で最初のプロジェクトを作成してください。",
|
||||
"other_actions": "その他の操作",
|
||||
"other_logs_and_files": "他のログとファイル",
|
||||
"over": "以上",
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
"add_comment": "코멘트 추가",
|
||||
"add_more_members": "더많은 멤버 추가",
|
||||
"add_to_folder": "폴더에 추가하기",
|
||||
"add_to_folders": "폴더 추가",
|
||||
"add_your_comment_here": "여기에 코멘트 추가",
|
||||
"add_your_first_group_member_now": "지금 첫 그룹 멤버 추가",
|
||||
"added": "추가완료",
|
||||
|
@ -142,7 +141,6 @@
|
|||
"create_new_folder": "새로운 폴더 만들기",
|
||||
"create_new_subscription": "새로운 구독 만들기",
|
||||
"create_project_in_github": "GitHub 저장소 만들기",
|
||||
"create_your_first_project": "첫 프로젝트를 만드세요!",
|
||||
"creating": "만드는 중",
|
||||
"credit_card": "신용카드",
|
||||
"cs": "Čeština",
|
||||
|
@ -380,7 +378,6 @@
|
|||
"open_project": "프로젝트 열기",
|
||||
"optional": "선택사항",
|
||||
"or": "또는",
|
||||
"or_create_project_left": "또는 왼쪽에 첫 프로젝트를 만드세요.",
|
||||
"other_actions": "다른 방법들",
|
||||
"other_logs_and_files": "기타 로그 및 파일 출력",
|
||||
"over": "더 많은",
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
"add_new_email": "Voeg nieuwe email toe",
|
||||
"add_role_and_department": "Voeg rol en afdeling toe",
|
||||
"add_to_folder": "Toevoegen aan map",
|
||||
"add_to_folders": "Aan mappen toevoegen",
|
||||
"add_your_comment_here": "Voeg uw opmerking hier toe",
|
||||
"add_your_first_group_member_now": "Voeg je eerste groepsleden nu toe",
|
||||
"added": "toegevoegd",
|
||||
|
@ -144,7 +143,6 @@
|
|||
"create_new_folder": "Nieuwe Map Maken",
|
||||
"create_new_subscription": "Nieuw Abonnement Maken",
|
||||
"create_project_in_github": "Een GitHub repository maken",
|
||||
"create_your_first_project": "Maak je eerste project!",
|
||||
"creating": "Aan het maken",
|
||||
"credit_card": "Creditcard",
|
||||
"cs": "Tsjechisch",
|
||||
|
@ -398,7 +396,6 @@
|
|||
"open_project": "Open Project",
|
||||
"optional": "Optioneel",
|
||||
"or": "of",
|
||||
"or_create_project_left": "of maak je eerste project aan de linkerkant.",
|
||||
"other_actions": "Andere acties",
|
||||
"other_logs_and_files": "Andere logs en bestanden",
|
||||
"over": "meer dan",
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
"add": "Legg til",
|
||||
"add_more_members": "Legg til flere medlemmer",
|
||||
"add_to_folder": "Legg til i mappe",
|
||||
"add_to_folders": "Legg til i mapper",
|
||||
"add_your_first_group_member_now": "Legg til ditt første gruppemedlem nå",
|
||||
"added": "lagt til",
|
||||
"adding": "Legge til",
|
||||
|
@ -98,7 +97,6 @@
|
|||
"create_new_folder": "Lag ny mappe",
|
||||
"create_new_subscription": "Lag nytt abonnement",
|
||||
"create_project_in_github": "Lag et GitHub-repository",
|
||||
"create_your_first_project": "Opprett ditt første prosjekt",
|
||||
"creating": "Oppretter",
|
||||
"credit_card": "Kredittkort",
|
||||
"cs": "Tsjekkisk",
|
||||
|
@ -264,7 +262,6 @@
|
|||
"online_latex_editor": "Online LaTeX-redigeringsprogram",
|
||||
"optional": "Valgfri",
|
||||
"or": "eller",
|
||||
"or_create_project_left": "eller opprett ditt første prosjekt til venstre.",
|
||||
"other_logs_and_files": "Andre logger & filer",
|
||||
"over": "over",
|
||||
"over_x_templates_easy_getting_started": "Vi har __over__ 400 __templates__ i malgalleriet vårt, så det er enkelt å komme i gang, enten du skriver en avhandling, et tidsskrift, CV eller noe annet.",
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
"copying": "kopiowanie",
|
||||
"create": "Utwórz",
|
||||
"create_new_folder": "Utwórz nowy folder",
|
||||
"create_your_first_project": "Utwórz swój pierwszy projekt!",
|
||||
"creating": "Tworzenie",
|
||||
"cs": "Czeski",
|
||||
"current_password": "Aktualne hasło",
|
||||
|
@ -136,7 +135,6 @@
|
|||
"one_collaborator": "Tylko jeden współpracownik",
|
||||
"one_free_collab": "Jeden darmowy współpracownik",
|
||||
"or": "lub",
|
||||
"or_create_project_left": "lub utwórz swój pierwszy projekt (z lewej).",
|
||||
"other_logs_and_files": "Inne logi i pliki",
|
||||
"owner": "Właściciel",
|
||||
"page_not_found": "Strona nie znaleziona",
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
"add_new_email": "Adicionar novo e-mail",
|
||||
"add_role_and_department": "Adicionar perfil e departamento",
|
||||
"add_to_folder": "Adicionar à pasta",
|
||||
"add_to_folders": "Adicionar à pasta",
|
||||
"add_your_comment_here": "Adicione seu comentário aqui",
|
||||
"add_your_first_group_member_now": "Adicione seu primeiro membro no grupo agora",
|
||||
"added": "adicionado",
|
||||
|
@ -173,7 +172,6 @@
|
|||
"create_new_folder": "Criar Nova Pasta",
|
||||
"create_new_subscription": "Crie Nova Inscrição",
|
||||
"create_project_in_github": "Criar um repositório no GitHub",
|
||||
"create_your_first_project": "Crie seu primeiro projeto",
|
||||
"creating": "Criando",
|
||||
"credit_card": "Cartão de Crédito",
|
||||
"cs": "Tcheco",
|
||||
|
@ -484,7 +482,6 @@
|
|||
"open_project": "Abrir Projeto",
|
||||
"optional": "Opcional",
|
||||
"or": "ou",
|
||||
"or_create_project_left": "ou crie seu primeiro projeto na esquerda",
|
||||
"other_actions": "Outras Ações",
|
||||
"other_logs_and_files": "Outros Logs & Arquivos",
|
||||
"over": "mais de",
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
"add": "Добавить",
|
||||
"add_more_members": "Добавить участников",
|
||||
"add_to_folder": "Переместить в папку",
|
||||
"add_to_folders": "Добавить в папки",
|
||||
"add_your_first_group_member_now": "Добавьте первых участников группы сейчас",
|
||||
"added": "добавлены",
|
||||
"adding": "Добавление",
|
||||
|
@ -110,7 +109,6 @@
|
|||
"create_new_folder": "Создать папку",
|
||||
"create_new_subscription": "Создать новую подписку",
|
||||
"create_project_in_github": "Создать проект на GitHub",
|
||||
"create_your_first_project": "Создайте свой первый проект!",
|
||||
"creating": "Создание",
|
||||
"credit_card": "банковская карта",
|
||||
"cs": "Чешский",
|
||||
|
@ -304,7 +302,6 @@
|
|||
"open_project": "Открыть проект",
|
||||
"optional": "Необязательный",
|
||||
"or": "или",
|
||||
"or_create_project_left": "или создайте свой первый проект слева.",
|
||||
"other_logs_and_files": "Другие логи и файлы",
|
||||
"over": "свыше",
|
||||
"over_x_templates_easy_getting_started": "В нашей галереи содержится __более__ 400 __шаблонов__, так что Вы можете легко начать работу над Вашей статьёй для журнала, диссертацией, резюме или любым другим документом.",
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
"add_new_email": "Lägg till ny e-postadress",
|
||||
"add_role_and_department": "Lägg till befattning och avdelning",
|
||||
"add_to_folder": "Lägg till i mapp",
|
||||
"add_to_folders": "Lägg till i mappar",
|
||||
"add_your_comment_here": "Skriv din kommentar här",
|
||||
"add_your_first_group_member_now": "Lägg till dina första gruppmedlemmar nu",
|
||||
"added": "lagst till",
|
||||
|
@ -223,7 +222,6 @@
|
|||
"create_new_folder": "Skapa ny mapp",
|
||||
"create_new_subscription": "Skapa en ny prenumeration",
|
||||
"create_project_in_github": "Skapa ett GitHub repo",
|
||||
"create_your_first_project": "Skapa ditt första projekt!",
|
||||
"creating": "Skapar",
|
||||
"credit_card": "Kreditkort",
|
||||
"cs": "Tjeckiska",
|
||||
|
@ -676,7 +674,6 @@
|
|||
"open_project": "Öppna projekt",
|
||||
"optional": "Valfritt",
|
||||
"or": "eller",
|
||||
"or_create_project_left": "eller skapa ditt första projekt till vänster.",
|
||||
"other_actions": "Andra åtgärder",
|
||||
"other_logs_and_files": "Andra loggar och filer",
|
||||
"other_output_files": "Ladda ner andra utdatafiler",
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
"add": "Ekle",
|
||||
"add_more_members": "Daha fazla üye ekleyin",
|
||||
"add_to_folder": "Klasöre ekle",
|
||||
"add_to_folders": "Klasörlere ekle",
|
||||
"add_your_first_group_member_now": "Grubunuza ilk üyeleri ekleyin",
|
||||
"added": "eklenmiş",
|
||||
"adding": "Ekleniyor",
|
||||
|
@ -96,7 +95,6 @@
|
|||
"create_new_folder": "Yeni Klasör Oluştur",
|
||||
"create_new_subscription": "Yeni Abonelik Oluştur",
|
||||
"create_project_in_github": "GitHub deposu oluştur",
|
||||
"create_your_first_project": "İlk projenizi oluşturun!",
|
||||
"creating": "Oluşturuluyor",
|
||||
"credit_card": "Kredi Kartı",
|
||||
"cs": "Çekçe",
|
||||
|
@ -256,7 +254,6 @@
|
|||
"online_latex_editor": "Çevrimiçi LaTeX Editörü",
|
||||
"optional": "İsteğe bağlı",
|
||||
"or": " ya da",
|
||||
"or_create_project_left": "ya da ilk projenizi sol taraftan oluşturabilirsiniz.",
|
||||
"other_logs_and_files": "Diğer sonuç dökümleri & dosyalar",
|
||||
"over": "fazla",
|
||||
"over_x_templates_easy_getting_started": "Şablon galerimizde sayısı 400’den __over__ olan __templates__ işe başlamanızı kolaylaştırabilir. Şablonlar arasında dergi makalesi, tez, CV ve daha fazlası bulunmaktadır.",
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
"add_new_email": "添加新电子邮件",
|
||||
"add_role_and_department": "添加角色和部门",
|
||||
"add_to_folder": "添加到目录",
|
||||
"add_to_folders": "添加到目录",
|
||||
"add_your_comment_here": "在此添加评论",
|
||||
"add_your_first_group_member_now": "现在添加您的第一个组成员",
|
||||
"added": "已添加",
|
||||
|
@ -228,7 +227,6 @@
|
|||
"create_new_folder": "创建新目录",
|
||||
"create_new_subscription": "新建订购",
|
||||
"create_project_in_github": "创建一个GitHub存储库",
|
||||
"create_your_first_project": "创建您的第一个项目!",
|
||||
"creating": "正在创建",
|
||||
"credit_card": "信用卡",
|
||||
"cs": "捷克语",
|
||||
|
@ -699,7 +697,6 @@
|
|||
"opted_out_linking": "您已选择取消将您的 <b>__email__</b> <b>__appName__</b> 帐户绑定到您的机构帐户。",
|
||||
"optional": "可选的",
|
||||
"or": "或者",
|
||||
"or_create_project_left": "或者在左边创建您的第一个项目",
|
||||
"other_actions": "其他",
|
||||
"other_logs_and_files": "其他日志和文件",
|
||||
"other_output_files": "下载其他输出文件",
|
||||
|
|
Loading…
Reference in a new issue