diff --git a/services/web/app/views/project/list.pug b/services/web/app/views/project/list.pug
deleted file mode 100644
index 9e0072ba69..0000000000
--- a/services/web/app/views/project/list.pug
+++ /dev/null
@@ -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
diff --git a/services/web/app/views/project/list/_current_plan_mixins.pug b/services/web/app/views/project/list/_current_plan_mixins.pug
deleted file mode 100644
index 3eef98fc90..0000000000
--- a/services/web/app/views/project/list/_current_plan_mixins.pug
+++ /dev/null
@@ -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
diff --git a/services/web/app/views/project/list/empty-project-list.pug b/services/web/app/views/project/list/empty-project-list.pug
deleted file mode 100644
index 0e21cf4fee..0000000000
--- a/services/web/app/views/project/list/empty-project-list.pug
+++ /dev/null
@@ -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)}
-
-
diff --git a/services/web/app/views/project/list/item.pug b/services/web/app/views/project/list/item.pug
deleted file mode 100644
index f325f0c166..0000000000
--- a/services/web/app/views/project/list/item.pug
+++ /dev/null
@@ -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")
diff --git a/services/web/app/views/project/list/notifications.pug b/services/web/app/views/project/list/notifications.pug
deleted file mode 100644
index b5cef5fda2..0000000000
--- a/services/web/app/views/project/list/notifications.pug
+++ /dev/null
@@ -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)
- | 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")}
diff --git a/services/web/app/views/project/list/project-list.pug b/services/web/app/views/project/list/project-list.pug
deleted file mode 100644
index 677be21bb8..0000000000
--- a/services/web/app/views/project/list/project-list.pug
+++ /dev/null
@@ -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")}
-
-
diff --git a/services/web/app/views/project/list/side-bar.pug b/services/web/app/views/project/list/side-bar.pug
deleted file mode 100644
index 6bcda818c4..0000000000
--- a/services/web/app/views/project/list/side-bar.pug
+++ /dev/null
@@ -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
diff --git a/services/web/app/views/translations/translation_message.pug b/services/web/app/views/translations/translation_message.pug
deleted file mode 100644
index a5b57320cb..0000000000
--- a/services/web/app/views/translations/translation_message.pug
+++ /dev/null
@@ -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")}
diff --git a/services/web/config/settings.defaults.js b/services/web/config/settings.defaults.js
index 46c8e7b151..c5617b8868 100644
--- a/services/web/config/settings.defaults.js
+++ b/services/web/config/settings.defaults.js
@@ -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: {
diff --git a/services/web/frontend/js/main/project-list/index.js b/services/web/frontend/js/main/project-list/index.js
index 4b55d00a9c..6b1205ad52 100644
--- a/services/web/frontend/js/main/project-list/index.js
+++ b/services/web/frontend/js/main/project-list/index.js
@@ -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'
diff --git a/services/web/frontend/js/main/project-list/left-hand-menu-promo-controller.js b/services/web/frontend/js/main/project-list/left-hand-menu-promo-controller.js
deleted file mode 100644
index a0d4dc1e56..0000000000
--- a/services/web/frontend/js/main/project-list/left-hand-menu-promo-controller.js
+++ /dev/null
@@ -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()
- }
-)
diff --git a/services/web/frontend/js/main/project-list/modal-controllers.js b/services/web/frontend/js/main/project-list/modal-controllers.js
index 3725d9f206..e553c0d90b 100644
--- a/services/web/frontend/js/main/project-list/modal-controllers.js
+++ b/services/web/frontend/js/main/project-list/modal-controllers.js
@@ -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'))
- }
-)
diff --git a/services/web/frontend/js/main/project-list/notifications-controller.js b/services/web/frontend/js/main/project-list/notifications-controller.js
deleted file mode 100644
index 015537e62a..0000000000
--- a/services/web/frontend/js/main/project-list/notifications-controller.js
+++ /dev/null
@@ -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
- })
- }
- }
-)
diff --git a/services/web/frontend/js/main/project-list/project-list.js b/services/web/frontend/js/main/project-list/project-list.js
deleted file mode 100644
index d50f71d552..0000000000
--- a/services/web/frontend/js/main/project-list/project-list.js
+++ /dev/null
@@ -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])
- })
- }
- }
-)
diff --git a/services/web/frontend/js/main/project-list/services/project-list.js b/services/web/frontend/js/main/project-list/services/project-list.js
deleted file mode 100644
index df74fede70..0000000000
--- a/services/web/frontend/js/main/project-list/services/project-list.js
+++ /dev/null
@@ -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'
- }
- },
- }
-})
diff --git a/services/web/locales/cs.json b/services/web/locales/cs.json
index 7148a7fe77..1af16bd797 100644
--- a/services/web/locales/cs.json
+++ b/services/web/locales/cs.json
@@ -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.",
diff --git a/services/web/locales/da.json b/services/web/locales/da.json
index bf63232e82..077fc61a08 100644
--- a/services/web/locales/da.json
+++ b/services/web/locales/da.json
@@ -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 __appName__–konto for __email__ 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",
diff --git a/services/web/locales/de.json b/services/web/locales/de.json
index b2f8c3796f..1d4bc8e16e 100644
--- a/services/web/locales/de.json
+++ b/services/web/locales/de.json
@@ -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 __email__ __appName__-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",
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index 4a6a89b9a9..98dd9b4a59 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -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 __email__ __appName__ 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",
diff --git a/services/web/locales/es.json b/services/web/locales/es.json
index 1ea4d1512e..332fe1a44e 100644
--- a/services/web/locales/es.json
+++ b/services/web/locales/es.json
@@ -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.",
diff --git a/services/web/locales/fi.json b/services/web/locales/fi.json
index d629c2cda5..d05659227d 100644
--- a/services/web/locales/fi.json
+++ b/services/web/locales/fi.json
@@ -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.",
diff --git a/services/web/locales/fr.json b/services/web/locales/fr.json
index 9f618986fa..6cd763768e 100644
--- a/services/web/locales/fr.json
+++ b/services/web/locales/fr.json
@@ -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 __appName__ __email__ à 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",
diff --git a/services/web/locales/it.json b/services/web/locales/it.json
index caa8e68255..fe1affeb06 100644
--- a/services/web/locales/it.json
+++ b/services/web/locales/it.json
@@ -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.",
diff --git a/services/web/locales/ja.json b/services/web/locales/ja.json
index 671699965c..a5afa8128d 100644
--- a/services/web/locales/ja.json
+++ b/services/web/locales/ja.json
@@ -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": "以上",
diff --git a/services/web/locales/ko.json b/services/web/locales/ko.json
index fea81d5c2d..b45d89c658 100644
--- a/services/web/locales/ko.json
+++ b/services/web/locales/ko.json
@@ -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": "더 많은",
diff --git a/services/web/locales/nl.json b/services/web/locales/nl.json
index 7a8554db4d..7066139f8a 100644
--- a/services/web/locales/nl.json
+++ b/services/web/locales/nl.json
@@ -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",
diff --git a/services/web/locales/no.json b/services/web/locales/no.json
index ba0a9ec015..1b6c9139f1 100644
--- a/services/web/locales/no.json
+++ b/services/web/locales/no.json
@@ -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.",
diff --git a/services/web/locales/pl.json b/services/web/locales/pl.json
index b6316bfeac..de7a903110 100644
--- a/services/web/locales/pl.json
+++ b/services/web/locales/pl.json
@@ -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",
diff --git a/services/web/locales/pt.json b/services/web/locales/pt.json
index f7bd6f1e34..81366a4da8 100644
--- a/services/web/locales/pt.json
+++ b/services/web/locales/pt.json
@@ -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",
diff --git a/services/web/locales/ru.json b/services/web/locales/ru.json
index fe36f09ccb..54bcbe7c61 100644
--- a/services/web/locales/ru.json
+++ b/services/web/locales/ru.json
@@ -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 __шаблонов__, так что Вы можете легко начать работу над Вашей статьёй для журнала, диссертацией, резюме или любым другим документом.",
diff --git a/services/web/locales/sv.json b/services/web/locales/sv.json
index 0e9e1f1c73..a4499a23e7 100644
--- a/services/web/locales/sv.json
+++ b/services/web/locales/sv.json
@@ -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",
diff --git a/services/web/locales/tr.json b/services/web/locales/tr.json
index a6c476b161..9070937e70 100644
--- a/services/web/locales/tr.json
+++ b/services/web/locales/tr.json
@@ -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.",
diff --git a/services/web/locales/zh-CN.json b/services/web/locales/zh-CN.json
index c5e6998c79..e48504fa8a 100644
--- a/services/web/locales/zh-CN.json
+++ b/services/web/locales/zh-CN.json
@@ -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": "您已选择取消将您的 __email__ __appName__ 帐户绑定到您的机构帐户。",
"optional": "可选的",
"or": "或者",
- "or_create_project_left": "或者在左边创建您的第一个项目",
"other_actions": "其他",
"other_logs_and_files": "其他日志和文件",
"other_output_files": "下载其他输出文件",