mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge branch 'master' into hb-fetch-licences-graph
This commit is contained in:
commit
29253c5a93
11 changed files with 114 additions and 56 deletions
|
@ -9,7 +9,7 @@ module.exports = InstitutionsAPI =
|
|||
method: 'GET'
|
||||
path: "/api/v2/institutions/#{institutionId.toString()}/affiliations"
|
||||
defaultErrorMessage: "Couldn't get institution affiliations"
|
||||
}, callback
|
||||
}, (error, body) -> callback(error, body or [])
|
||||
|
||||
getInstitutionLicences: (institutionId, startDate, endDate, lag, callback = (error, body) ->) ->
|
||||
makeAffiliationRequest {
|
||||
|
@ -24,7 +24,7 @@ module.exports = InstitutionsAPI =
|
|||
method: 'GET'
|
||||
path: "/api/v2/users/#{userId.toString()}/affiliations"
|
||||
defaultErrorMessage: "Couldn't get user affiliations"
|
||||
}, callback
|
||||
}, (error, body) -> callback(error, body or [])
|
||||
|
||||
|
||||
addAffiliation: (userId, email, affiliationOptions, callback) ->
|
||||
|
|
|
@ -1,45 +1,4 @@
|
|||
div#history(ng-show="ui.view == 'history'")
|
||||
span
|
||||
.upgrade-prompt(ng-if="project.features.versioning === false && ui.view === 'history'")
|
||||
.message(ng-if="project.owner._id == user.id")
|
||||
p.text-center: strong #{translate("upgrade_to_get_feature", {feature:"full Project History"})}
|
||||
p.text-center.small(ng-show="startedFreeTrial") #{translate("refresh_page_after_starting_free_trial")}
|
||||
ul.list-unstyled
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("unlimited_projects")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("collabs_per_proj", {collabcount:'Multiple'})}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("full_doc_history")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("sync_to_dropbox")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("sync_to_github")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
|#{translate("compile_larger_projects")}
|
||||
p.text-center(ng-controller="FreeTrialModalController")
|
||||
a.btn.btn-success(
|
||||
href
|
||||
ng-class="buttonClass"
|
||||
ng-click="startFreeTrial('history')"
|
||||
) #{translate("start_free_trial")}
|
||||
|
||||
.message(ng-show="project.owner._id != user.id")
|
||||
p #{translate("ask_proj_owner_to_upgrade_for_history")}
|
||||
p
|
||||
a.small(href, ng-click="toggleHistory()") #{translate("cancel")}
|
||||
|
||||
include ./history/entriesListV1
|
||||
include ./history/entriesListV2
|
||||
|
||||
|
|
|
@ -6,11 +6,13 @@ aside.change-list(
|
|||
ng-if="!history.showOnlyLabels && !history.error"
|
||||
entries="history.updates"
|
||||
current-user="user"
|
||||
current-user-is-owner="project.owner._id === user.id"
|
||||
users="projectUsers"
|
||||
load-entries="loadMore()"
|
||||
load-disabled="history.loading || history.atEnd"
|
||||
load-initialize="ui.view == 'history'"
|
||||
is-loading="history.loading"
|
||||
free-history-limit-hit="history.freeHistoryLimitHit"
|
||||
on-entry-select="handleEntrySelect(selectedEntry)"
|
||||
on-label-delete="handleLabelDelete(label)"
|
||||
)
|
||||
|
@ -134,6 +136,48 @@ script(type="text/ng-template", id="historyEntriesListTpl")
|
|||
.loading(ng-show="$ctrl.isLoading")
|
||||
i.fa.fa-spin.fa-refresh
|
||||
| #{translate("loading")}...
|
||||
.history-entries-list-upgrade-prompt(
|
||||
ng-if="$ctrl.freeHistoryLimitHit && $ctrl.currentUserIsOwner"
|
||||
ng-controller="FreeTrialModalController"
|
||||
)
|
||||
p #{translate("currently_seeing_only_24_hrs_history")}
|
||||
p: strong #{translate("upgrade_to_get_feature", {feature:"full Project History"})}
|
||||
ul.list-unstyled
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("unlimited_projects")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("collabs_per_proj", {collabcount:'Multiple'})}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("full_doc_history")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("sync_to_dropbox")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
| #{translate("sync_to_github")}
|
||||
|
||||
li
|
||||
i.fa.fa-check
|
||||
|#{translate("compile_larger_projects")}
|
||||
p.text-center
|
||||
a.btn.btn-success(
|
||||
href
|
||||
ng-class="buttonClass"
|
||||
ng-click="startFreeTrial('history')"
|
||||
) #{translate("start_free_trial")}
|
||||
p.small(ng-show="startedFreeTrial") #{translate("refresh_page_after_starting_free_trial")}
|
||||
.history-entries-list-upgrade-prompt(
|
||||
ng-if="$ctrl.freeHistoryLimitHit && !$ctrl.currentUserIsOwner"
|
||||
)
|
||||
p #{translate("currently_seeing_only_24_hrs_history")}
|
||||
strong #{translate("ask_proj_owner_to_upgrade_for_full_history")}
|
||||
|
||||
script(type="text/ng-template", id="historyEntryTpl")
|
||||
.history-entry(
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
i.fa.fa-spin.fa-refresh
|
||||
| #{translate("loading")}...
|
||||
span.history-toolbar-selected-version(
|
||||
ng-show="!history.loadingFileTree && !history.showOnlyLabels && !history.error"
|
||||
ng-show="!history.loadingFileTree && !history.showOnlyLabels && history.selection.updates.length && !history.error"
|
||||
) #{translate("browsing_project_as_of")}
|
||||
time.history-toolbar-time {{ history.selection.updates[0].meta.end_ts | formatDate:'Do MMM YYYY, h:mm a' }}
|
||||
span.history-toolbar-selected-version(
|
||||
|
@ -19,13 +19,13 @@
|
|||
button.history-toolbar-btn(
|
||||
ng-click="showAddLabelDialog();"
|
||||
ng-if="!history.showOnlyLabels"
|
||||
ng-disabled="history.loadingFileTree"
|
||||
ng-disabled="history.loadingFileTree || history.selection.updates.length == 0"
|
||||
)
|
||||
i.fa.fa-tag
|
||||
| #{translate("history_label_this_version")}
|
||||
button.history-toolbar-btn(
|
||||
ng-click="toggleHistoryViewMode();"
|
||||
ng-disabled="history.loadingFileTree"
|
||||
ng-disabled="history.loadingFileTree || history.selection.updates.length == 0"
|
||||
)
|
||||
i.fa.fa-exchange
|
||||
| #{translate("compare_to_another_version")}
|
||||
|
|
|
@ -305,7 +305,7 @@ div.full-size.pdf(ng-controller="PdfController")
|
|||
dbl-click-callback="syncToCode"
|
||||
)
|
||||
iframe(
|
||||
ng-src="{{ pdf.url }}"
|
||||
ng-src="{{ pdf.url | trusted }}"
|
||||
ng-if="settings.pdfViewer == 'native'"
|
||||
)
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ define [
|
|||
viewMode: null
|
||||
nextBeforeTimestamp: null
|
||||
atEnd: false
|
||||
userHasFullFeature: @$scope.project?.features?.versioning or false
|
||||
freeHistoryLimitHit: false
|
||||
selection: {
|
||||
label: null
|
||||
updates: []
|
||||
|
@ -232,9 +234,11 @@ define [
|
|||
@$scope.history.labels = @_sortLabelsByVersionAndDate response.labels.data
|
||||
@_loadUpdates(updatesData.updates)
|
||||
@$scope.history.nextBeforeTimestamp = updatesData.nextBeforeTimestamp
|
||||
if !updatesData.nextBeforeTimestamp?
|
||||
if !updatesData.nextBeforeTimestamp? or @$scope.history.freeHistoryLimitHit
|
||||
@$scope.history.atEnd = true
|
||||
@$scope.history.loading = false
|
||||
if @$scope.history.updates.length == 0
|
||||
@$scope.history.loadingFileTree = false
|
||||
.catch (error) =>
|
||||
{ status, statusText } = error
|
||||
@$scope.history.error = { status, statusText }
|
||||
|
@ -387,23 +391,34 @@ define [
|
|||
|
||||
_loadUpdates: (updates = []) ->
|
||||
previousUpdate = @$scope.history.updates[@$scope.history.updates.length - 1]
|
||||
|
||||
for update in updates or []
|
||||
dateTimeNow = new Date()
|
||||
timestamp24hoursAgo = dateTimeNow.setDate(dateTimeNow.getDate() - 1)
|
||||
cutOffIndex = null
|
||||
|
||||
for update, i in updates or []
|
||||
for user in update.meta.users or []
|
||||
if user?
|
||||
user.hue = ColorManager.getHueForUserId(user.id)
|
||||
|
||||
if !previousUpdate? or !moment(previousUpdate.meta.end_ts).isSame(update.meta.end_ts, "day")
|
||||
update.meta.first_in_day = true
|
||||
|
||||
|
||||
update.selectedFrom = false
|
||||
update.selectedTo = false
|
||||
update.inSelection = false
|
||||
|
||||
previousUpdate = update
|
||||
|
||||
if !@$scope.history.userHasFullFeature and update.meta.end_ts < timestamp24hoursAgo
|
||||
cutOffIndex = i or 1 # Make sure that we show at least one entry (to allow labelling).
|
||||
@$scope.history.freeHistoryLimitHit = true
|
||||
break
|
||||
|
||||
firstLoad = @$scope.history.updates.length == 0
|
||||
|
||||
if !@$scope.history.userHasFullFeature and cutOffIndex?
|
||||
updates = updates.slice 0, cutOffIndex
|
||||
|
||||
@$scope.history.updates =
|
||||
@$scope.history.updates.concat(updates)
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ define [
|
|||
loadInitialize: "<"
|
||||
isLoading: "<"
|
||||
currentUser: "<"
|
||||
freeHistoryLimitHit: "<"
|
||||
currentUserIsOwner: "<"
|
||||
onEntrySelect: "&"
|
||||
onLabelDelete: "&"
|
||||
controller: historyEntriesListController
|
||||
|
|
|
@ -12,6 +12,10 @@ define [
|
|||
# and then again on ack.
|
||||
AUTO_COMPILE_DEBOUNCE = 2000
|
||||
|
||||
App.filter('trusted', ['$sce', ($sce)->
|
||||
return (url)-> return $sce.trustAsResourceUrl(url);
|
||||
])
|
||||
|
||||
App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, logHintsFeedback, localStorage) ->
|
||||
# enable per-user containers by default
|
||||
perUserCompile = true
|
||||
|
@ -226,7 +230,7 @@ define [
|
|||
|
||||
buildPdfDownloadUrl = (pdfDownloadDomain, path)->
|
||||
#we only download builds from compiles server for security reasons
|
||||
if pdfDownloadDomain? and path.indexOf("build") != -1
|
||||
if pdfDownloadDomain? and path? and path.indexOf("build") != -1
|
||||
return "#{pdfDownloadDomain}#{path}"
|
||||
else
|
||||
return path
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: (@line-height-computed / 2);
|
||||
}
|
||||
.history-toolbar-time,
|
||||
.history-toolbar-selected-label {
|
||||
|
@ -33,7 +34,7 @@
|
|||
.btn-xs;
|
||||
padding-left: @padding-small-horizontal;
|
||||
padding-right: @padding-small-horizontal;
|
||||
margin-left: (@line-height-computed / 2);
|
||||
margin-right: (@line-height-computed / 2);
|
||||
}
|
||||
.history-toolbar-entries-list {
|
||||
flex: 0 0 @changesListWidth;
|
||||
|
@ -173,6 +174,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
.history-entries-list-upgrade-prompt {
|
||||
background-color: #FFF;
|
||||
margin-bottom: 2px;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.history-labels-list {
|
||||
.history-entries;
|
||||
overflow-y: auto;
|
||||
|
|
|
@ -11,12 +11,12 @@ describe "InstitutionsAPI", ->
|
|||
|
||||
beforeEach ->
|
||||
@logger = err: sinon.stub(), log: ->
|
||||
settings = apis: { v1: { url: 'v1.url', user: '', pass: '' } }
|
||||
@settings = apis: { v1: { url: 'v1.url', user: '', pass: '' } }
|
||||
@request = sinon.stub()
|
||||
@InstitutionsAPI = SandboxedModule.require modulePath, requires:
|
||||
"logger-sharelatex": @logger
|
||||
"metrics-sharelatex": timeAsyncMethod: sinon.stub()
|
||||
'settings-sharelatex': settings
|
||||
'settings-sharelatex': @settings
|
||||
'request': @request
|
||||
|
||||
@stubbedUser =
|
||||
|
@ -40,6 +40,14 @@ describe "InstitutionsAPI", ->
|
|||
should.not.exist(requestOptions.body)
|
||||
body.should.equal responseBody
|
||||
done()
|
||||
|
||||
it 'handle empty response', (done)->
|
||||
@settings.apis = null
|
||||
@InstitutionsAPI.getInstitutionAffiliations @institutionId, (err, body) =>
|
||||
should.not.exist(err)
|
||||
expect(body).to.be.a 'Array'
|
||||
body.length.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'getInstitutionLicences', ->
|
||||
it 'get licences', (done)->
|
||||
|
@ -85,6 +93,14 @@ describe "InstitutionsAPI", ->
|
|||
err.message.should.have.string body.errors
|
||||
done()
|
||||
|
||||
it 'handle empty response', (done)->
|
||||
@settings.apis = null
|
||||
@InstitutionsAPI.getUserAffiliations @stubbedUser._id, (err, body) =>
|
||||
should.not.exist(err)
|
||||
expect(body).to.be.a 'Array'
|
||||
body.length.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'addAffiliation', ->
|
||||
beforeEach ->
|
||||
@request.callsArgWith(1, null, { statusCode: 201 })
|
||||
|
|
|
@ -4,16 +4,21 @@ define ['ide/history/HistoryV2Manager'], (HistoryV2Manager) ->
|
|||
@scope =
|
||||
$watch: sinon.stub()
|
||||
$on: sinon.stub()
|
||||
project:
|
||||
features:
|
||||
versioning: true
|
||||
@ide = {}
|
||||
@historyManager = new HistoryV2Manager(@ide, @scope)
|
||||
|
||||
it "should setup the history scope on intialization", ->
|
||||
it "should setup the history scope on initialization", ->
|
||||
expect(@scope.history).to.deep.equal({
|
||||
isV2: true
|
||||
updates: []
|
||||
viewMode: null
|
||||
nextBeforeTimestamp: null
|
||||
atEnd: false
|
||||
userHasFullFeature: true
|
||||
freeHistoryLimitHit: false
|
||||
selection: {
|
||||
label: null
|
||||
updates: []
|
||||
|
@ -32,6 +37,12 @@ define ['ide/history/HistoryV2Manager'], (HistoryV2Manager) ->
|
|||
selectedFile: null
|
||||
})
|
||||
|
||||
|
||||
it "should setup history without full access to the feature if the project does not have versioning", ->
|
||||
@scope.project.features.versioning = false
|
||||
@historyManager = new HistoryV2Manager(@ide, @scope)
|
||||
expect(@scope.history.userHasFullFeature).to.equal false
|
||||
|
||||
describe "_perDocSummaryOfUpdates", ->
|
||||
it "should return the range of updates for the docs", ->
|
||||
result = @historyManager._perDocSummaryOfUpdates([{
|
||||
|
|
Loading…
Reference in a new issue