Przeglądaj źródła

Teardown old project list frontend code (#11950)

* Remove frontend project list angular code (pugfiles + controllers)

* Remove unused translation keys in every language

GitOrigin-RevId: e0514721d6a32ca2de7d1be9433da3476ba1680c
M Fahru 3 lat temu
rodzic
commit
3e315eada1
33 zmienionych plików z 1 dodań i 2370 usunięć
  1. 0 80
      services/web/app/views/project/list.pug
  2. 0 112
      services/web/app/views/project/list/_current_plan_mixins.pug
  3. 0 82
      services/web/app/views/project/list/empty-project-list.pug
  4. 0 136
      services/web/app/views/project/list/item.pug
  5. 0 286
      services/web/app/views/project/list/notifications.pug
  6. 0 223
      services/web/app/views/project/list/project-list.pug
  7. 0 135
      services/web/app/views/project/list/side-bar.pug
  8. 0 8
      services/web/app/views/translations/translation_message.pug
  9. 1 1
      services/web/config/settings.defaults.js
  10. 0 3
      services/web/frontend/js/main/project-list/index.js
  11. 0 14
      services/web/frontend/js/main/project-list/left-hand-menu-promo-controller.js
  12. 0 108
      services/web/frontend/js/main/project-list/modal-controllers.js
  13. 0 141
      services/web/frontend/js/main/project-list/notifications-controller.js
  14. 0 949
      services/web/frontend/js/main/project-list/project-list.js
  15. 0 35
      services/web/frontend/js/main/project-list/services/project-list.js
  16. 0 3
      services/web/locales/cs.json
  17. 0 3
      services/web/locales/da.json
  18. 0 3
      services/web/locales/de.json
  19. 0 7
      services/web/locales/en.json
  20. 0 3
      services/web/locales/es.json
  21. 0 3
      services/web/locales/fi.json
  22. 0 3
      services/web/locales/fr.json
  23. 0 3
      services/web/locales/it.json
  24. 0 3
      services/web/locales/ja.json
  25. 0 3
      services/web/locales/ko.json
  26. 0 3
      services/web/locales/nl.json
  27. 0 3
      services/web/locales/no.json
  28. 0 2
      services/web/locales/pl.json
  29. 0 3
      services/web/locales/pt.json
  30. 0 3
      services/web/locales/ru.json
  31. 0 3
      services/web/locales/sv.json
  32. 0 3
      services/web/locales/tr.json
  33. 0 3
      services/web/locales/zh-CN.json

+ 0 - 80
services/web/app/views/project/list.pug

@@ -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

+ 0 - 112
services/web/app/views/project/list/_current_plan_mixins.pug

@@ -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

+ 0 - 82
services/web/app/views/project/list/empty-project-list.pug

@@ -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)}
-
-							

+ 0 - 136
services/web/app/views/project/list/item.pug

@@ -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")

+ 0 - 286
services/web/app/views/project/list/notifications.pug

@@ -1,286 +0,0 @@
-include ../../_mixins/reconfirm_affiliation
-
-.user-notifications(ng-controller="NotificationsController")
-	ul.list-unstyled(
-		ng-if="notifications.length > 0 && projects.length > 0",
-		ng-cloak
-	)
-		li.notification-entry(
-			ng-repeat="notification in notifications"
-		)
-			div(ng-switch="notification.templateKey" ng-hide="notification.hide")
-				.alert.alert-info(
-					ng-switch-when="notification_project_invite",
-					ng-controller="ProjectInviteNotificationController"
-				)
-					.notification-body
-						span(ng-show="!notification.accepted") !{translate("notification_project_invite_message", { userName: "{{ userName }}", projectName: "{{ projectName }}" })}
-						span(ng-show="notification.accepted") !{translate("notification_project_invite_accepted_message", { projectName: "{{ projectName }}" })}
-					.notification-action
-						a.pull-right.btn.btn-sm.btn-info(
-							ng-show="notification.accepted",
-							href="/project/{{ notification.messageOpts.projectId }}"
-						) #{translate("open_project")}
-						a.pull-right.btn.btn-sm.btn-info(
-							href,
-							ng-click="accept()",
-							ng-disabled="notification.inflight",
-							ng-show="!notification.accepted"
-						)
-							span(ng-show="!notification.inflight") #{translate("join_project")}
-							span(ng-show="notification.inflight")
-								i.fa.fa-fw.fa-spinner.fa-spin(aria-hidden="true")
-								|  
-								| #{translate("joining")}…
-					.notification-close
-						button(ng-click="dismiss(notification)").close.pull-right
-							span(aria-hidden="true") ×
-							span.sr-only #{translate("close")}
-				.alert.alert-info(
-					ng-switch-when="wfh_2020_upgrade_offer"
-				)
-					.notification-body
-						span Important notice: Your free WFH2020 upgrade came to an end on June 30th 2020. We're still providing a number of special initiatives to help you continue collaborating throughout 2020.
-					.notification-action
-						a.pull-right.btn.btn-sm.btn-info(href="https://www.overleaf.com/events/wfh2020") View
-					.notification-close
-						button(ng-click="dismiss(notification)").close.pull-right
-							span(aria-hidden="true") ×
-							span.sr-only #{translate("close")}
-				.alert.alert-info(
-					ng-switch-when="notification_ip_matched_affiliation"
-					ng-if="notification.messageOpts.ssoEnabled"
-				)
-					.notification-body
-						| !{translate("looks_like_youre_at", {institutionName: '{{notification.messageOpts.university_name}}'}, ['strong'])}
-						br
-						| !{translate("you_can_now_log_in_sso", {}, ['strong'])}
-						br
-						| #{translate("link_institutional_email_get_started", {}, ['strong'])} 
-						a(
-							ng-href="{{notification.messageOpts.portalPath || 'https://www.overleaf.com/learn/how-to/Institutional_Login'}}"
-						) #{translate("find_out_more_nt")}
-					.notification-action
-						a.pull-right.btn.btn-sm.btn-info(
-							ng-href=`{{samlInitPath}}?university_id={{notification.messageOpts.institutionId}}&auto=/project`
-						)
-							| #{translate("link_account")}
-					.notification-close
-						button.btn-sm(ng-click="dismiss(notification)").close.pull-right
-							span(aria-hidden="true") ×
-							span.sr-only #{translate("close")}
-				.alert.alert-info(
-					ng-switch-when="notification_ip_matched_affiliation"
-					ng-if="!notification.messageOpts.ssoEnabled"
-				)
-					.notification-body
-						| !{translate("looks_like_youre_at", {institutionName: '{{notification.messageOpts.university_name}}'}, ['strong'])}
-						br
-						| !{translate("did_you_know_institution_providing_professional", {institutionName: '{{notification.messageOpts.university_name}}'}, ['strong'])}
-						br
-						| #{translate("add_email_to_claim_features")}
-					.notification-action
-						a.pull-right.btn.btn-sm.btn-info(
-							href="/user/settings"
-						) #{translate("add_affiliation")}
-					.notification-close
-						button.btn-sm(ng-click="dismiss(notification)").close.pull-right
-							span(aria-hidden="true") ×
-							span.sr-only #{translate("close")}
-
-				.alert.alert-danger(
-					ng-switch-when="notification_tpds_file_limit"
-				)
-					.notification-body
-						| Error: Your project
-						strong  {{ notification.messageOpts.projectName }}
-						|	has gone over the 2000 file limit using an integration (e.g. Dropbox or GitHub) <br/>
-						| Please decrease the size of your project to prevent further errors.
-					.notification-action
-						a.pull-right.btn.btn-sm.btn-info(href="/user/settings")
-							| Account Settings
-					.notification-close
-						button.btn-sm(ng-click="dismiss(notification)").close.pull-right
-							span(aria-hidden="true") &times;
-							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'])}
-							| &nbsp;
-							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") &times;
-							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")}
-						| &nbsp;
-						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") &times;
-							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") &times;
-							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})}&nbsp;
-							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") &times;
-							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") &times;
-							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") &times;
-							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")
-							| &nbsp;#{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") &times;
-							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')}&hellip;
-					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") &times;
-							span.sr-only #{translate("close")}

+ 0 - 223
services/web/app/views/project/list/project-list.pug

@@ -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")}
-
-							

+ 0 - 135
services/web/app/views/project/list/side-bar.pug

@@ -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

+ 0 - 8
services/web/app/views/translations/translation_message.pug

@@ -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") &times;
-				span.sr-only #{translate("close")}

+ 1 - 1
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: {

+ 0 - 3
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'

+ 0 - 14
services/web/frontend/js/main/project-list/left-hand-menu-promo-controller.js

@@ -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()
-  }
-)

+ 0 - 108
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'))
-  }
-)

+ 0 - 141
services/web/frontend/js/main/project-list/notifications-controller.js

@@ -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
-        })
-    }
-  }
-)

+ 0 - 949
services/web/frontend/js/main/project-list/project-list.js

@@ -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])
-      })
-    }
-  }
-)

+ 0 - 35
services/web/frontend/js/main/project-list/services/project-list.js

@@ -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'
-      }
-    },
-  }
-})

+ 0 - 3
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.",

+ 0 - 3
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 <b>__appName__</b>–konto for <b>__email__</b> til din institutionelle konto.",
   "optional": "Valgfrit",
   "or": "eller",
-  "or_create_project_left": "eller opret dit første projekt til venstre.",
   "other_actions": "Andre handlinger",
   "other_logs_and_files": "Andre logger og filer",
   "other_output_files": "Hent andre udfiler",

+ 0 - 3
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 <b>__email__</b> <b>__appName__</b>-Kontos mit deinem institutionellen Konto entschieden.",
   "optional": "Freiwillig",
   "or": "oder",
-  "or_create_project_left": "oder erstelle dein erstes Projekt auf der linken Seite.",
   "organization": "Organisation",
   "other_actions": "Weitere Aktionen",
   "other_logs_and_files": "Andere Protokolle und Dateien",

+ 0 - 7
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 <b>__email__</b> <b>__appName__</b> account to your institutional account.",
   "optional": "Optional",
   "or": "or",
-  "or_create_project_left": "or create your first project on the left.",
   "organization": "Organization",
   "organization_type": "Organization Type",
   "organize_projects": "Organize Projects",
@@ -1530,7 +1524,6 @@
   "tagline_student_annual": "Save even more",
   "tagline_student_monthly": "Great for a single term",
   "tags": "Tags",
-  "tags_slash_folders": "Tags/Folders",
   "take_me_home": "Take me home!",
   "take_short_survey": "Take a short survey",
   "tc_everyone": "Everyone",

+ 0 - 3
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.",

+ 0 - 3
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 &amp; 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.",

+ 0 - 3
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 <b>__appName__</b> <b>__email__</b> à votre compte institutionnel.",
   "optional": "Optionnel",
   "or": "ou",
-  "or_create_project_left": "ou créez votre premier projet à gauche.",
   "other_actions": "Autres actions",
   "other_logs_and_files": "Autres journaux et fichiers",
   "other_output_files": "Télécharger les autres fichiers générés",

+ 0 - 3
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 &amp; 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.",

+ 0 - 3
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": "以上",

+ 0 - 3
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": "더 많은",

+ 0 - 3
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",

+ 0 - 3
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 &amp; 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.",

+ 0 - 2
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",

+ 0 - 3
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 &amp; Arquivos",
   "over": "mais de",

+ 0 - 3
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 __шаблонов__, так что Вы можете легко начать работу над Вашей статьёй для журнала, диссертацией, резюме или любым другим документом.",

+ 0 - 3
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",

+ 0 - 3
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 &amp; 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.",

+ 0 - 3
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": "您已选择取消将您的 <b>__email__</b> <b>__appName__</b> 帐户绑定到您的机构帐户。",
   "optional": "可选的",
   "or": "或者",
-  "or_create_project_left": "或者在左边创建您的第一个项目",
   "other_actions": "其他",
   "other_logs_and_files": "其他日志和文件",
   "other_output_files": "下载其他输出文件",