mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-27 19:11:56 +02:00
Merge pull request #2807 from overleaf/ns-project-import-deletion-dashboard
Clean up references to v1 projects on project dashboard GitOrigin-RevId: e574382fb1747da7a701808148434f4d689cbe33
This commit is contained in:
@@ -29,7 +29,6 @@ const PackageVersions = require('../../infrastructure/PackageVersions')
|
||||
const Sources = require('../Authorization/Sources')
|
||||
const TokenAccessHandler = require('../TokenAccess/TokenAccessHandler')
|
||||
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
|
||||
const Modules = require('../../infrastructure/Modules')
|
||||
const ProjectEntityHandler = require('./ProjectEntityHandler')
|
||||
const TpdsProjectFlusher = require('../ThirdPartyDataStore/TpdsProjectFlusher')
|
||||
const UserGetter = require('../User/UserGetter')
|
||||
@@ -326,7 +325,6 @@ const ProjectController = {
|
||||
// _buildProjectList already converts archived/trashed to booleans so isArchivedOrTrashed should not be used here
|
||||
projects = ProjectController._buildProjectList(projects, userId)
|
||||
.filter(p => !(p.archived || p.trashed))
|
||||
.filter(p => !p.isV1Project)
|
||||
.map(p => ({ _id: p.id, name: p.name, accessLevel: p.accessLevel }))
|
||||
|
||||
res.json({ projects })
|
||||
@@ -380,22 +378,6 @@ const ProjectController = {
|
||||
cb
|
||||
)
|
||||
},
|
||||
v1Projects(cb) {
|
||||
if (!Features.hasFeature('overleaf-integration')) {
|
||||
return cb(null, null)
|
||||
}
|
||||
|
||||
Modules.hooks.fire('findAllV1Projects', userId, (error, projects) => {
|
||||
if (projects == null) {
|
||||
projects = []
|
||||
}
|
||||
if (error != null && error instanceof V1ConnectionError) {
|
||||
noV1Connection = true
|
||||
return cb(null, null)
|
||||
}
|
||||
cb(error, projects[0])
|
||||
})
|
||||
}, // hooks.fire returns an array of results, only need first
|
||||
hasSubscription(cb) {
|
||||
LimitationsManager.hasPaidSubscription(
|
||||
currentUser,
|
||||
@@ -433,20 +415,13 @@ const ProjectController = {
|
||||
logger.warn({ err }, 'error getting data for project list page')
|
||||
return next(err)
|
||||
}
|
||||
if (noV1Connection) {
|
||||
results.v1Projects = results.v1Projects || { projects: [], tags: [] }
|
||||
results.v1Projects.noConnection = true
|
||||
}
|
||||
const { notifications, user, userAffiliations } = results
|
||||
// Handle case of deleted user
|
||||
if (user == null) {
|
||||
UserController.logout(req, res, next)
|
||||
return
|
||||
}
|
||||
const v1Tags =
|
||||
(results.v1Projects != null ? results.v1Projects.tags : undefined) ||
|
||||
[]
|
||||
const tags = results.tags.concat(v1Tags)
|
||||
const tags = results.tags
|
||||
const notificationsInstitution = []
|
||||
for (const notification of notifications) {
|
||||
notification.html = req.i18n.translate(
|
||||
@@ -545,12 +520,9 @@ const ProjectController = {
|
||||
)
|
||||
const projects = ProjectController._buildProjectList(
|
||||
results.projects,
|
||||
userId,
|
||||
results.v1Projects != null ? results.v1Projects.projects : undefined
|
||||
)
|
||||
const warnings = ProjectController._buildWarningsList(
|
||||
results.v1Projects
|
||||
userId
|
||||
)
|
||||
const warnings = ProjectController._buildWarningsList(noV1Connection)
|
||||
|
||||
// in v2 add notifications for matching university IPs
|
||||
if (Settings.overleaf != null && req.ip !== user.lastLoginIp) {
|
||||
@@ -573,9 +545,6 @@ const ProjectController = {
|
||||
userAffiliations,
|
||||
hasSubscription: results.hasSubscription,
|
||||
institutionLinkingError,
|
||||
isShowingV1Projects:
|
||||
results.v1Projects != null &&
|
||||
results.v1Projects.projects.length > 0,
|
||||
warnings,
|
||||
zipFileSizeLimit: Settings.maxUploadSize
|
||||
}
|
||||
@@ -863,11 +832,8 @@ const ProjectController = {
|
||||
)
|
||||
},
|
||||
|
||||
_buildProjectList(allProjects, userId, v1Projects) {
|
||||
_buildProjectList(allProjects, userId) {
|
||||
let project
|
||||
if (v1Projects == null) {
|
||||
v1Projects = []
|
||||
}
|
||||
const {
|
||||
owned,
|
||||
readAndWrite,
|
||||
@@ -907,9 +873,6 @@ const ProjectController = {
|
||||
)
|
||||
)
|
||||
}
|
||||
for (project of v1Projects) {
|
||||
projects.push(ProjectController._buildV1ProjectViewModel(project))
|
||||
}
|
||||
// Token-access
|
||||
// Only add these projects if they're not already present, this gives us cascading access
|
||||
// from 'owner' => 'token-read-only'
|
||||
@@ -973,39 +936,6 @@ const ProjectController = {
|
||||
return model
|
||||
},
|
||||
|
||||
_buildV1ProjectViewModel(project) {
|
||||
const archived = project.archived
|
||||
// If a project is simultaneously trashed and archived, we will consider it archived but not trashed.
|
||||
const trashed = project.removed && !archived
|
||||
|
||||
const projectViewModel = {
|
||||
id: project.id,
|
||||
name: project.title,
|
||||
lastUpdated: new Date(project.updated_at * 1000), // Convert from epoch
|
||||
archived: archived,
|
||||
trashed: trashed,
|
||||
isV1Project: true
|
||||
}
|
||||
if (
|
||||
(project.owner != null && project.owner.user_is_owner) ||
|
||||
(project.creator != null && project.creator.user_is_creator)
|
||||
) {
|
||||
projectViewModel.accessLevel = 'owner'
|
||||
} else {
|
||||
projectViewModel.accessLevel = 'readOnly'
|
||||
}
|
||||
if (project.owner != null) {
|
||||
projectViewModel.owner = {
|
||||
first_name: project.owner.name
|
||||
}
|
||||
} else if (project.creator != null) {
|
||||
projectViewModel.owner = {
|
||||
first_name: project.creator.name
|
||||
}
|
||||
}
|
||||
return projectViewModel
|
||||
},
|
||||
|
||||
_injectProjectUsers(projects, callback) {
|
||||
const users = {}
|
||||
for (const project of projects) {
|
||||
@@ -1051,22 +981,12 @@ const ProjectController = {
|
||||
)
|
||||
},
|
||||
|
||||
_buildWarningsList(v1ProjectData) {
|
||||
if (v1ProjectData == null) {
|
||||
v1ProjectData = {}
|
||||
}
|
||||
const warnings = []
|
||||
if (v1ProjectData.noConnection) {
|
||||
warnings.push(
|
||||
'Error accessing Overleaf V1. Some of your projects or features may be missing.'
|
||||
)
|
||||
}
|
||||
if (v1ProjectData.hasHiddenV1Projects) {
|
||||
warnings.push(
|
||||
"Looks like you've got a lot of V1 projects! Some of them may be hidden on V2. To view them all, use the V1 dashboard."
|
||||
)
|
||||
}
|
||||
return warnings
|
||||
_buildWarningsList(noConnection) {
|
||||
return noConnection
|
||||
? [
|
||||
'Error accessing Overleaf V1. Some of your projects or features may be missing.'
|
||||
]
|
||||
: []
|
||||
},
|
||||
|
||||
_buildPortalTemplatesList(affiliations) {
|
||||
|
||||
@@ -104,7 +104,6 @@ html(
|
||||
include layout/footer
|
||||
|
||||
!= moduleIncludes("contactModal", locals)
|
||||
include v1-tooltip
|
||||
|
||||
block foot-scripts
|
||||
script(src=buildJsPath('libraries.js'))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
td.project-list-table-name-cell(ng-if-start="!project.isV1Project")
|
||||
td.project-list-table-name-cell
|
||||
.project-list-table-name-container
|
||||
input.project-list-table-select-item(
|
||||
select-individual,
|
||||
@@ -61,7 +61,7 @@ td.project-list-table-lastupdated-cell
|
||||
| {{getUserName(project.lastUpdatedBy)}}
|
||||
|
||||
|
||||
td.project-list-table-actions-cell(ng-if-end)
|
||||
td.project-list-table-actions-cell
|
||||
div(
|
||||
ng-if="!project.isTableActionInflight"
|
||||
)
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
li(
|
||||
ng-repeat="tag in tags | orderBy:'name'",
|
||||
ng-controller="TagDropdownItemController"
|
||||
ng-if="!tag.isV1"
|
||||
)
|
||||
a(href="#", ng-click="addOrRemoveProjectsFromTag()", stop-propagation="click")
|
||||
i.fa(
|
||||
@@ -204,7 +203,6 @@
|
||||
select-row
|
||||
)
|
||||
include ./item
|
||||
include ./v1-item
|
||||
tr(
|
||||
ng-if="visibleProjects.length == 0",
|
||||
ng-cloak
|
||||
|
||||
@@ -76,9 +76,6 @@
|
||||
tooltip-append-to-body="true"
|
||||
stop-propagation="click"
|
||||
) i
|
||||
if isShowingV1Projects
|
||||
li(ng-class="{active: (filter == 'v1')}", ng-click="filterProjects('v1')")
|
||||
a(href) #{translate("v1_projects")}
|
||||
li.separator
|
||||
h2 #{translate("tags_slash_folders")}
|
||||
li.tag(ng-cloak)
|
||||
@@ -102,14 +99,8 @@
|
||||
)
|
||||
span.name {{tag.name}}
|
||||
span.subdued ({{countProjectsForTag(tag)}})
|
||||
span.v1-badge(
|
||||
ng-if="tag.isV1",
|
||||
ng-cloak,
|
||||
aria-label=translate("v1_badge")
|
||||
tooltip-template="'v1TagTooltipTemplate'"
|
||||
tooltip-append-to-body="true"
|
||||
)
|
||||
span.dropdown.tag-menu(dropdown)(ng-if="!tag.isV1")
|
||||
|
||||
span.dropdown.tag-menu(dropdown)
|
||||
a.dropdown-toggle(
|
||||
href="#",
|
||||
data-toggle="dropdown",
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
td.project-list-table-name-cell(ng-if-start="project.isV1Project")
|
||||
.project-list-table-name-container
|
||||
span.project-list-table-v1-badge-container
|
||||
span.v1-badge(
|
||||
aria-label=translate("v1_badge")
|
||||
tooltip-template="'v1ProjectTooltipTemplate'"
|
||||
tooltip-append-to-body="true"
|
||||
)
|
||||
span.project-list-table-name
|
||||
a.projectName(href='/{{project.id}}') {{project.name}}
|
||||
|
||||
td.project-list-table-owner-cell
|
||||
span.owner {{ownerName(project)}}
|
||||
|
||||
td.project-list-table-lastupdated-cell(
|
||||
ng-if-end
|
||||
colspan="2"
|
||||
)
|
||||
span.last-modified(tooltip="{{project.lastUpdated | formatDate}}") {{project.lastUpdated | fromNowDate}}
|
||||
@@ -1,6 +0,0 @@
|
||||
script(type="text/ng-template", id="v1ProjectTooltipTemplate")
|
||||
span This project is from Overleaf v1 and has not yet been automatically or manually imported to v2.
|
||||
|
||||
|
||||
script(type="text/ng-template", id="v1TagTooltipTemplate")
|
||||
span This folder/tag is from Overleaf v1. Once these projects are moved to v2 the tag will also move.
|
||||
@@ -240,11 +240,6 @@ App.controller('ProjectPageController', function(
|
||||
visible = false
|
||||
}
|
||||
|
||||
// Hide projects from V1 if we only want to see shared projects
|
||||
if ($scope.filter === 'shared' && project.isV1Project) {
|
||||
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
|
||||
@@ -274,10 +269,6 @@ App.controller('ProjectPageController', function(
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope.filter === 'v1' && !project.isV1Project) {
|
||||
visible = false
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
$scope.visibleProjects.push(project)
|
||||
} else {
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
@import 'app/sprites.less';
|
||||
@import 'app/invite.less';
|
||||
@import 'app/error-pages.less';
|
||||
@import 'app/v1-badge.less';
|
||||
@import 'app/editor/history-v2.less';
|
||||
@import 'app/metrics.less';
|
||||
@import 'app/open-in-overleaf.less';
|
||||
|
||||
@@ -179,10 +179,6 @@ input.project-list-table-select-item[type='checkbox'] {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.project-list-table-v1-badge-container {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.project-list-table-name {
|
||||
display: inline-block;
|
||||
padding-left: @line-height-computed * 1.5;
|
||||
@@ -532,10 +528,6 @@ ul.project-list {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.v1-badge {
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 0 0.3em;
|
||||
margin-left: 0.2em;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
.v1-badge {
|
||||
&:extend(.label);
|
||||
&:extend(.label-default);
|
||||
vertical-align: 11%;
|
||||
padding: 1px 3px;
|
||||
margin: 0 6px;
|
||||
&:before {
|
||||
content: 'V1';
|
||||
}
|
||||
}
|
||||
@@ -102,11 +102,6 @@ describe('ProjectController', function() {
|
||||
.stub()
|
||||
.callsArgWith(2, null, { lastLoginIp: '192.170.18.2' })
|
||||
}
|
||||
this.Modules = {
|
||||
hooks: {
|
||||
fire: sinon.stub()
|
||||
}
|
||||
}
|
||||
this.Features = {
|
||||
hasFeature: sinon.stub()
|
||||
}
|
||||
@@ -171,7 +166,6 @@ describe('ProjectController', function() {
|
||||
.AuthenticationController,
|
||||
'../TokenAccess/TokenAccessHandler': this.TokenAccessHandler,
|
||||
'../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
|
||||
'../../infrastructure/Modules': this.Modules,
|
||||
'./ProjectEntityHandler': this.ProjectEntityHandler,
|
||||
'../Errors/Errors': Errors,
|
||||
'../../infrastructure/Features': this.Features,
|
||||
@@ -424,10 +418,7 @@ describe('ProjectController', function() {
|
||||
null,
|
||||
this.allProjects
|
||||
)
|
||||
this.Modules.hooks.fire
|
||||
.withArgs('findAllV1Projects', this.user._id)
|
||||
.yields(undefined)
|
||||
}) // Without integration module hook, cb returns undefined
|
||||
})
|
||||
|
||||
it('should render the project/list page', function(done) {
|
||||
this.res.render = (pageName, opts) => {
|
||||
@@ -521,17 +512,6 @@ describe('ProjectController', function() {
|
||||
'Error accessing Overleaf V1. Some of your projects or features may be missing.'
|
||||
})
|
||||
|
||||
it('should show a warning when there is an error getting v1 projects', function(done) {
|
||||
this.Modules.hooks.fire
|
||||
.withArgs('findAllV1Projects', this.user._id)
|
||||
.yields(new Errors.V1ConnectionError('error'))
|
||||
this.res.render = (pageName, opts) => {
|
||||
expect(opts.warnings).to.contain(this.connectionWarning)
|
||||
done()
|
||||
}
|
||||
this.ProjectController.projectListPage(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should show a warning when there is an error getting subscriptions from v1', function(done) {
|
||||
this.LimitationsManager.hasPaidSubscription.yields(
|
||||
new Errors.V1ConnectionError('error')
|
||||
@@ -593,82 +573,6 @@ describe('ProjectController', function() {
|
||||
})
|
||||
})
|
||||
|
||||
describe('with overleaf-integration-web-module hook', function() {
|
||||
beforeEach(function() {
|
||||
this.Features.hasFeature = sinon
|
||||
.stub()
|
||||
.withArgs('overleaf-integration')
|
||||
.returns(true)
|
||||
this.V1Response = {
|
||||
projects: [
|
||||
{
|
||||
id: '123mockV1Id',
|
||||
title: 'mock title',
|
||||
updated_at: 1509616411,
|
||||
removed: false,
|
||||
archived: false
|
||||
},
|
||||
{
|
||||
id: '456mockV1Id',
|
||||
title: 'mock title 2',
|
||||
updated_at: 1509616411,
|
||||
removed: true,
|
||||
archived: false
|
||||
}
|
||||
],
|
||||
tags: [{ name: 'mock tag', project_ids: ['123mockV1Id'] }]
|
||||
}
|
||||
this.Modules.hooks.fire
|
||||
.withArgs('findAllV1Projects', this.user._id)
|
||||
.yields(null, [this.V1Response])
|
||||
}) // Need to wrap response in array, as multiple hooks could fire
|
||||
|
||||
it('should include V1 projects', function(done) {
|
||||
this.res.render = (pageName, opts) => {
|
||||
opts.projects.length.should.equal(
|
||||
this.projects.length +
|
||||
this.collabertions.length +
|
||||
this.readOnly.length +
|
||||
this.tokenReadAndWrite.length +
|
||||
this.tokenReadOnly.length +
|
||||
this.V1Response.projects.length
|
||||
)
|
||||
opts.projects.forEach(p => {
|
||||
// Check properties correctly mapped from V1
|
||||
expect(p).to.have.property('id')
|
||||
expect(p).to.have.property('name')
|
||||
expect(p).to.have.property('lastUpdated')
|
||||
expect(p).to.have.property('accessLevel')
|
||||
expect(p).to.have.property('archived')
|
||||
})
|
||||
done()
|
||||
}
|
||||
this.ProjectController.projectListPage(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should include V1 tags', function(done) {
|
||||
this.res.render = (pageName, opts) => {
|
||||
opts.tags.length.should.equal(
|
||||
this.tags.length + this.V1Response.tags.length
|
||||
)
|
||||
opts.tags.forEach(t => {
|
||||
expect(t).to.have.property('name')
|
||||
expect(t).to.have.property('project_ids')
|
||||
})
|
||||
done()
|
||||
}
|
||||
this.ProjectController.projectListPage(this.req, this.res)
|
||||
})
|
||||
|
||||
it('should have isShowingV1Projects flag', function(done) {
|
||||
this.res.render = (pageName, opts) => {
|
||||
opts.isShowingV1Projects.should.equal(true)
|
||||
done()
|
||||
}
|
||||
this.ProjectController.projectListPage(this.req, this.res)
|
||||
})
|
||||
})
|
||||
|
||||
describe('With Institution SSO feature', function() {
|
||||
beforeEach(function(done) {
|
||||
this.institutionEmail = 'test@overleaf.com'
|
||||
@@ -952,10 +856,7 @@ describe('ProjectController', function() {
|
||||
null,
|
||||
this.allProjects
|
||||
)
|
||||
this.Modules.hooks.fire
|
||||
.withArgs('findAllV1Projects', this.user._id)
|
||||
.yields(undefined)
|
||||
}) // Without integration module hook, cb returns undefined
|
||||
})
|
||||
|
||||
it('should render the project/list page', function(done) {
|
||||
this.res.render = (pageName, opts) => {
|
||||
|
||||
Reference in New Issue
Block a user