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