diff --git a/services/web/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index fd65454054..83eb72fcf7 100755 --- a/services/web/app/coffee/Features/Compile/ClsiManager.coffee +++ b/services/web/app/coffee/Features/Compile/ClsiManager.coffee @@ -111,8 +111,11 @@ module.exports = ClsiManager = ClsiManager._buildRequest project_id, options, (error, req) -> compilerUrl = ClsiManager._getCompilerUrl(options?.compileGroup) filename = file || req?.compile?.rootResourcePath + wordcount_url = "#{compilerUrl}/project/#{project_id}/wordcount?file=#{encodeURIComponent(filename)}" + if req.compile.options.imageName? + wordcount_url += "&image=#{encodeURIComponent(req.compile.options.imageName)}" request.get { - url: "#{compilerUrl}/project/#{project_id}/wordcount?file=#{filename}" + url: wordcount_url }, (error, response, body) -> return callback(error) if error? if 200 <= response.statusCode < 300 diff --git a/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee index 338c660c0c..f12a7d548e 100644 --- a/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEditorHandler.coffee @@ -26,6 +26,8 @@ module.exports = ProjectEditorHandler = dropbox:false compileTimeout: 60 compileGroup:"standard" + templates: false + references: false if project.owner_ref.features? if project.owner_ref.features.collaborators? @@ -37,7 +39,11 @@ module.exports = ProjectEditorHandler = if project.owner_ref.features.compileTimeout? result.features.compileTimeout = project.owner_ref.features.compileTimeout if project.owner_ref.features.compileGroup? - result.features.compileGroup = project.owner_ref.features.compileGroup + result.features.compileGroup = project.owner_ref.features.compileGroup + if project.owner_ref.features.templates? + result.features.templates = project.owner_ref.features.templates + if project.owner_ref.features.references? + result.features.references = project.owner_ref.features.references result.owner = @buildUserModelView project.owner_ref, "owner" diff --git a/services/web/app/coffee/Features/StaticPages/StaticPagesRouter.coffee b/services/web/app/coffee/Features/StaticPages/StaticPagesRouter.coffee index f1079cc5b7..f1f55814c7 100644 --- a/services/web/app/coffee/Features/StaticPages/StaticPagesRouter.coffee +++ b/services/web/app/coffee/Features/StaticPages/StaticPagesRouter.coffee @@ -13,6 +13,7 @@ module.exports = webRouter.get '/privacy_policy', HomeController.externalPage("privacy", "Privacy Policy") webRouter.get '/planned_maintenance', HomeController.externalPage("planned_maintenance", "Planned Maintenance") webRouter.get '/style', HomeController.externalPage("style_guide", "Style Guide") + webRouter.get '/jobs', HomeController.externalPage("jobs", "Jobs") webRouter.get '/dropbox', HomeController.externalPage("dropbox", "Dropbox and ShareLaTeX") diff --git a/services/web/app/coffee/models/User.coffee b/services/web/app/coffee/models/User.coffee index af83318b49..8fca181d0e 100644 --- a/services/web/app/coffee/models/User.coffee +++ b/services/web/app/coffee/models/User.coffee @@ -34,6 +34,8 @@ UserSchema = new Schema github: { type:Boolean, default: Settings.defaultFeatures.github } compileTimeout: { type:Number, default: Settings.defaultFeatures.compileTimeout } compileGroup: { type:String, default: Settings.defaultFeatures.compileGroup } + templates: { type:Boolean, default: Settings.defaultFeatures.templates } + references: { type:Boolean, default: Settings.defaultFeatures.references } } featureSwitches : { pdfng: { type: Boolean } diff --git a/services/web/app/views/project/editor/publish-template.jade b/services/web/app/views/project/editor/publish-template.jade index 7fd2c1a0f4..c89aeebe6d 100644 --- a/services/web/app/views/project/editor/publish-template.jade +++ b/services/web/app/views/project/editor/publish-template.jade @@ -6,46 +6,84 @@ script(type="text/ng-template", id="publishProjectAsTemplateModalTemplate") ng-click="cancel()" ) × h3 #{translate("publish_as_template")} - .modal-body.modal-body-share - span(ng-hide="problemTalkingToTemplateApi") - form() - label(for='Description') #{translate("template_description")} - .form-group - textarea.form-control( - rows=5, - name='Description', - ng-model="templateDetails.description", - value="" - ) - div(ng-show="templateDetails.exists").text-center.templateDetails - | #{translate("project_last_published_at")} - strong {{templateDetails.publishedDate}}. - a(ng-href="{{templateDetails.canonicalUrl}}") #{translate("view_in_template_gallery")}. + div(ng-if="project.features.templates") + .modal-body.modal-body-share + span(ng-hide="problemTalkingToTemplateApi") + form() + label(for='Description') #{translate("template_description")} + .form-group + textarea.form-control( + rows=5, + name='Description', + ng-model="templateDetails.description", + value="" + ) + div(ng-show="templateDetails.exists").text-center.templateDetails + | #{translate("project_last_published_at")} + strong {{templateDetails.publishedDate}}. + a(ng-href="{{templateDetails.canonicalUrl}}") #{translate("view_in_template_gallery")}. - span(ng-show="problemTalkingToTemplateApi") #{translate("problem_talking_to_publishing_service")}. + span(ng-show="problemTalkingToTemplateApi") #{translate("problem_talking_to_publishing_service")}. + + .modal-footer(ng-hide="problemTalkingToTemplateApi") + button.btn.btn-default( + ng-click="cancel()", + ng-disabled="state.publishInflight || state.unpublishInflight" + ) + span #{translate("cancel")} + button.btn.btn-info( + ng-click="unpublishTemplate()", + ng-disabled="state.publishInflight || state.unpublishInflight" + ng-show="templateDetails.exists" + ) + span(ng-show="!state.unpublishInflight") #{translate("unpublish")} + span(ng-show="state.unpublishInflight") #{translate("unpublishing")}... + button.btn.btn-primary( + ng-click="publishTemplate()", + ng-disabled="state.publishInflight || state.unpublishInflight" + ) + span(ng-show="!state.publishInflight && !templateDetails.exists") #{translate("publish")} + span(ng-show="!state.publishInflight && templateDetails.exists") #{translate("republish")} + span(ng-show="state.publishInflight") #{translate("publishing")}... + div(ng-hide="project.features.templates") + .modal-body.modal-body-share + p #{translate("upgrade_to_get_feature", {feature:"templates"})} - .modal-footer(ng-hide="problemTalkingToTemplateApi") - button.btn.btn-default( - ng-click="cancel()", - ng-disabled="state.publishInflight || state.unpublishInflight" - ) - span #{translate("cancel")} + 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")} - button.btn.btn-info( - ng-click="unpublishTemplate()", - ng-disabled="state.publishInflight || state.unpublishInflight" - ng-show="templateDetails.exists" - ) - span(ng-show="!state.unpublishInflight") #{translate("unpublish")} - span(ng-show="state.unpublishInflight") #{translate("unpublishing")}... + li + i.fa.fa-check   + | #{translate("sync_to_github")} - button.btn.btn-primary( - ng-click="publishTemplate()", - ng-disabled="state.publishInflight || state.unpublishInflight" - ) - span(ng-show="!state.publishInflight && !templateDetails.exists") #{translate("publish")} - span(ng-show="!state.publishInflight && templateDetails.exists") #{translate("republish")} - span(ng-show="state.publishInflight") #{translate("publishing")}... \ No newline at end of file + li + i.fa.fa-check   + |#{translate("compile_larger_projects")} + + .modal-footer(ng-controller="FreeTrialModalController") + .text-center + a.btn.btn-success( + href + ng-class="buttonClass" + ng-click="startFreeTrial('templates')" + ) #{translate("start_free_trial")} + + .row-spaced-small.small(ng-show="startedFreeTrial") + | #{translate("refresh_page_after_starting_free_trial")} diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 9f47f33a9f..cdfe451c1a 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -143,6 +143,8 @@ module.exports = versioning: true compileTimeout: 60 compileGroup: "standard" + references: true + templates: true plans: plans = [{ planCode: "personal" diff --git a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee index e47f72daca..00e02af13e 100644 --- a/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee +++ b/services/web/test/UnitTests/coffee/Compile/ClsiManagerTests.coffee @@ -266,7 +266,7 @@ describe "ClsiManager", -> describe "wordCount", -> beforeEach -> @request.get = sinon.stub().callsArgWith(1, null, {statusCode: 200}, @body = { mock: "foo" }) - @ClsiManager._buildRequest = sinon.stub().callsArgWith(2, null, { compile: { rootResourcePath: "rootfile.text" } }) + @ClsiManager._buildRequest = sinon.stub().callsArgWith(2, null, @req = { compile: { rootResourcePath: "rootfile.text", options: {} } }) @ClsiManager._getCompilerUrl = sinon.stub().returns "compiler.url" describe "with root file", -> @@ -289,3 +289,13 @@ describe "ClsiManager", -> @request.get .calledWith({ url: "compiler.url/project/#{@project_id}/wordcount?file=main.tex" }) .should.equal true + + describe "with image", -> + beforeEach -> + @req.compile.options.imageName = @image = "example.com/mock/image" + @ClsiManager.wordCount @project_id, "main.tex", {}, @callback + + it "should call wordCount with file and image", -> + @request.get + .calledWith({ url: "compiler.url/project/#{@project_id}/wordcount?file=main.tex&image=#{encodeURIComponent(@image)}" }) + .should.equal true