diff --git a/controllers/api.go b/controllers/api.go index a5f6cefb..5acfb83b 100644 --- a/controllers/api.go +++ b/controllers/api.go @@ -2,6 +2,7 @@ package controllers import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -350,19 +351,56 @@ func API_Import_Group(w http.ResponseWriter, r *http.Request) { return } JSONResponse(w, ts, http.StatusOK) + return } // API_Import_Email allows for the importing of email. // Returns a Message object func API_Import_Email(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { - body, err := ioutil.ReadAll(r.Body) - if err != nil { - Logger.Println(err) - } - w.Header().Set("Content-Type", "text/plain") - fmt.Fprintf(w, "%s", body) + if r.Method != "POST" { + JSONResponse(w, models.Response{Success: false, Message: "Method not allowed"}, http.StatusBadRequest) + return } + body, err := ioutil.ReadAll(r.Body) + if err != nil { + Logger.Println(err) + } + w.Header().Set("Content-Type", "text/plain") + fmt.Fprintf(w, "%s", body) + return +} + +// API_Import_Site allows for the importing of HTML from a website +// Without "include_resources" set, it will merely place a "base" tag +// so that all resources can be loaded relative to the given URL. +func API_Import_Site(w http.ResponseWriter, r *http.Request) { + cr := cloneRequest{} + if r.Method != "POST" { + JSONResponse(w, models.Response{Success: false, Message: "Method not allowed"}, http.StatusBadRequest) + return + } + err := json.NewDecoder(r.Body).Decode(&cr) + if err != nil { + JSONResponse(w, models.Response{Success: false, Message: "Error decoding JSON Request"}, http.StatusBadRequest) + return + } + if err = cr.validate(); err != nil { + JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest) + return + } + resp, err := http.Get(cr.URL) + if err != nil { + JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest) + return + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest) + return + } + cs := cloneResponse{HTML: string(body)} + JSONResponse(w, cs, http.StatusOK) + return } // JSONResponse attempts to set the status code, c, and marshal the given interface, d, into a response that @@ -377,3 +415,19 @@ func JSONResponse(w http.ResponseWriter, d interface{}, c int) { w.WriteHeader(c) fmt.Fprintf(w, "%s", dj) } + +type cloneRequest struct { + URL string `json:"url"` + IncludeResources bool `json:"include_resources"` +} + +func (cr *cloneRequest) validate() error { + if cr.URL == "" { + return errors.New("No URL Specified") + } + return nil +} + +type cloneResponse struct { + HTML string `json:"html"` +} diff --git a/controllers/route.go b/controllers/route.go index 2c1cdf50..0a572220 100644 --- a/controllers/route.go +++ b/controllers/route.go @@ -31,8 +31,6 @@ func CreateAdminRouter() http.Handler { router.HandleFunc("/logout", Use(Logout, mid.RequireLogin)) router.HandleFunc("/register", Register) router.HandleFunc("/settings", Use(Settings, mid.RequireLogin)) - router.HandleFunc("/html/preview", Use(Preview, mid.RequireLogin)) - router.HandleFunc("/html/clone", Use(Clone, mid.RequireLogin)) // Create the API routes api := router.PathPrefix("/api").Subrouter() api = api.StrictSlash(true) @@ -48,6 +46,7 @@ func CreateAdminRouter() http.Handler { api.HandleFunc("/pages/{id:[0-9]+}", Use(API_Pages_Id, mid.RequireAPIKey)) api.HandleFunc("/import/group", API_Import_Group) api.HandleFunc("/import/email", API_Import_Email) + api.HandleFunc("/import/site", API_Import_Site) // Setup static file serving router.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/"))) diff --git a/static/js/app/controllers.js b/static/js/app/controllers.js index c02b1bfe..fa417a66 100644 --- a/static/js/app/controllers.js +++ b/static/js/app/controllers.js @@ -257,7 +257,7 @@ var CampaignModalCtrl = function($scope, CampaignService, $modalInstance) { $scope.editGroupTableParams.reload() }; $scope.cancel = function() { - $modalInstance.dismiss('cancel'); + $modalInstance.dismiss(); }; $scope.ok = function(campaign) { var newCampaign = new CampaignService(campaign); @@ -613,7 +613,7 @@ var GroupModalCtrl = function($scope, GroupService, $modalInstance, $upload) { }) } }; -} +}; app.controller('TemplateCtrl', function($scope, $modal, TemplateService, ngTableParams) { $scope.errorFlash = function(message) { @@ -795,14 +795,13 @@ var ImportEmailCtrl = function($scope, $http, $modalInstance) { ).success(function(data) {console.log("Success: " + data)}) .error(function(data) {console.log("Error: " + data)}); $modalInstance.close($scope.email.raw) -}; -$scope.cancel = function() {$modalInstance.dismiss()} -}; + }; +} app.controller('LandingPageCtrl', function($scope, $modal, LandingPageService, ngTableParams) { $scope.errorFlash = function(message) { - $scope.flashes = []; - $scope.flashes.push({ + $scope.flashes = {"main" : [], "modal" : []}; + $scope.flashes.modal.push({ "type": "danger", "message": message, "icon": "fa-exclamation-circle" @@ -810,8 +809,8 @@ app.controller('LandingPageCtrl', function($scope, $modal, LandingPageService, n } $scope.successFlash = function(message) { - $scope.flashes = []; - $scope.flashes.push({ + $scope.flashes = {"main" : [], "modal" : []};; + $scope.flashes.modal.push({ "type": "success", "message": message, "icon": "fa-check-circle" @@ -892,22 +891,84 @@ app.controller('LandingPageCtrl', function($scope, $modal, LandingPageService, n } }); -var LandingPageModalCtrl = function($scope, $modalInstance) { +var LandingPageModalCtrl = function($scope, $modalInstance, $http) { $scope.editorOptions = { fullPage: true, allowedContent: true, startupMode: "source" } + $scope.errorFlash = function(message) { + $scope.flashes = {"main" : [], "modal" : []}; + $scope.flashes.modal.push({ + "type": "danger", + "message": message, + "icon": "fa-exclamation-circle" + }) + } + + $scope.successFlash = function(message) { + $scope.flashes = {"main" : [], "modal" : []};; + $scope.flashes.modal.push({ + "type": "success", + "message": message, + "icon": "fa-check-circle" + }) + } + $scope.cloneSite = function() { + var siteModalInstance = $modal.open({ + templateUrl: '/js/app/partials/modals/siteCloneModal.html', //<---- Need to make this + controller: SiteCloneCtrl, + scope: $scope + }); + siteModalInstance.result.then(function(data) { + $scope.successFlash(data.message) + $scope.html = data.html; + }, function() {}); + }; $scope.cancel = function() { - $modalInstance.dismiss('cancel'); + $modalInstance.dismiss(); }; $scope.ok = function(page) { $modalInstance.dismiss('') $scope.savePage(page) }; - $scope.csrf_token = csrf_token }; +var SiteCloneCtrl = function($scope, $modalInstance, $http) { + $scope.errorFlash = function(message) { + $scope.flashes = {"main" : [], "modal" : []}; + $scope.flashes.modal.push({ + "type": "danger", + "message": message, + "icon": "fa-exclamation-circle" + }) + } + $scope.ok = function() { + if ($scope.url == "") { + $scope.errorFlash("No URL Specified") + return + } + $http.post({ + method: "POST", + url: "/api/import/site", + data: { + "url" : $scope.url, + "include_resources" : $scope.include_resources + }, + headers : { + "Content-Type" : "application/json" + } + }).success(function(response){ + $modalInstance.close(response); + }).error(function(response){ + $scope.errorFlash(response.message) + }); + } + $scope.cancel = function() { + $modalInstance.dismiss(); + }; +} + app.controller('SettingsCtrl', function($scope, $http, $window) { $scope.flashes = []; $scope.user = user; diff --git a/static/js/app/partials/modals/landingPageModal.html b/static/js/app/partials/modals/landingPageModal.html index 4539e38e..786c0cd4 100644 --- a/static/js/app/partials/modals/landingPageModal.html +++ b/static/js/app/partials/modals/landingPageModal.html @@ -5,7 +5,11 @@