Merge pull request #7 from adamarthurryan/simple-interface
Simple interface
This commit is contained in:
commit
b63474b3ae
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
bin
|
||||||
node_modules
|
node_modules
|
||||||
public
|
public
|
||||||
.tmp
|
.tmp
|
||||||
@ -5,5 +6,5 @@ public
|
|||||||
.idea
|
.idea
|
||||||
client/bower_components
|
client/bower_components
|
||||||
dist
|
dist
|
||||||
/server/config/local.env.js
|
server/config/local.env.js
|
||||||
wdiff-1.2.2
|
wdiff-1.2.2
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.config(function ($routeProvider) {
|
|
||||||
$routeProvider
|
|
||||||
.when('/login', {
|
|
||||||
templateUrl: 'app/account/login/login.html',
|
|
||||||
controller: 'LoginCtrl'
|
|
||||||
})
|
|
||||||
.when('/signup', {
|
|
||||||
templateUrl: 'app/account/signup/signup.html',
|
|
||||||
controller: 'SignupCtrl'
|
|
||||||
})
|
|
||||||
.when('/settings', {
|
|
||||||
templateUrl: 'app/account/settings/settings.html',
|
|
||||||
controller: 'SettingsCtrl',
|
|
||||||
authenticate: true
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,29 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('LoginCtrl', function ($scope, Auth, $location, $window) {
|
|
||||||
$scope.user = {};
|
|
||||||
$scope.errors = {};
|
|
||||||
|
|
||||||
$scope.login = function(form) {
|
|
||||||
$scope.submitted = true;
|
|
||||||
|
|
||||||
if(form.$valid) {
|
|
||||||
Auth.login({
|
|
||||||
email: $scope.user.email,
|
|
||||||
password: $scope.user.password
|
|
||||||
})
|
|
||||||
.then( function() {
|
|
||||||
// Logged in, redirect to home
|
|
||||||
$location.path('/');
|
|
||||||
})
|
|
||||||
.catch( function(err) {
|
|
||||||
$scope.errors.other = err.message;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.loginOauth = function(provider) {
|
|
||||||
$window.location.href = '/auth/' + provider;
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,42 +0,0 @@
|
|||||||
div(ng-include='"components/navbar/navbar.html"')
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-sm-12
|
|
||||||
h1 Login
|
|
||||||
|
|
||||||
.col-sm-12
|
|
||||||
form.form(name='form', ng-submit='login(form)', novalidate='')
|
|
||||||
.form-group
|
|
||||||
label Email
|
|
||||||
input.form-control(type='text', name='email', ng-model='user.email')
|
|
||||||
.form-group
|
|
||||||
label Password
|
|
||||||
input.form-control(type='password', name='password', ng-model='user.password')
|
|
||||||
|
|
||||||
.form-group.has-error
|
|
||||||
p.help-block(ng-show='form.email.$error.required && form.password.$error.required && submitted')
|
|
||||||
| Please enter your email and password.
|
|
||||||
p.help-block {{ errors.other }}
|
|
||||||
|
|
||||||
div
|
|
||||||
button.btn.btn-inverse.btn-lg.btn-login(type='submit')
|
|
||||||
| Login
|
|
||||||
= ' '
|
|
||||||
a.btn.btn-default.btn-lg.btn-register(href='/signup')
|
|
||||||
| Register
|
|
||||||
|
|
||||||
hr
|
|
||||||
|
|
||||||
div
|
|
||||||
a.btn.btn-facebook(href='', ng-click='loginOauth("facebook")')
|
|
||||||
i.fa.fa-facebook
|
|
||||||
| Connect with Facebook
|
|
||||||
= ' '
|
|
||||||
a.btn.btn-google-plus(href='', ng-click='loginOauth("google")')
|
|
||||||
i.fa.fa-google-plus
|
|
||||||
| Connect with Google+
|
|
||||||
= ' '
|
|
||||||
a.btn.btn-twitter(href='', ng-click='loginOauth("twitter")')
|
|
||||||
i.fa.fa-twitter
|
|
||||||
| Connect with Twitter
|
|
||||||
hr
|
|
@ -1,30 +0,0 @@
|
|||||||
// Colors
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
$btnText: #fff;
|
|
||||||
$btnTextAlt: #000;
|
|
||||||
|
|
||||||
$btnFacebookBackground: #3B5998;
|
|
||||||
$btnFacebookBackgroundHighlight: #133783;
|
|
||||||
$btnTwitterBackground: #2daddc;
|
|
||||||
$btnTwitterBackgroundHighlight: #0271bf;
|
|
||||||
$btnGooglePlusBackground: #dd4b39;
|
|
||||||
$btnGooglePlusBackgroundHighlight: #c53727;
|
|
||||||
$btnGithubBackground: #fafafa;
|
|
||||||
$btnGithubBackgroundHighlight: #ccc;
|
|
||||||
|
|
||||||
// Social buttons
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
.btn-facebook {
|
|
||||||
@include button-variant($btnText, $btnFacebookBackgroundHighlight, $btnFacebookBackgroundHighlight);
|
|
||||||
}
|
|
||||||
.btn-twitter {
|
|
||||||
@include button-variant($btnText, $btnTwitterBackground, $btnTwitterBackgroundHighlight);
|
|
||||||
}
|
|
||||||
.btn-google-plus {
|
|
||||||
@include button-variant($btnText, $btnGooglePlusBackground, $btnGooglePlusBackgroundHighlight);
|
|
||||||
}
|
|
||||||
.btn-github {
|
|
||||||
@include button-variant($btnTextAlt, $btnGithubBackground, $btnGithubBackgroundHighlight);
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('SettingsCtrl', function ($scope, User, Auth) {
|
|
||||||
$scope.errors = {};
|
|
||||||
|
|
||||||
$scope.changePassword = function(form) {
|
|
||||||
$scope.submitted = true;
|
|
||||||
if(form.$valid) {
|
|
||||||
Auth.changePassword( $scope.user.oldPassword, $scope.user.newPassword )
|
|
||||||
.then( function() {
|
|
||||||
$scope.message = 'Password successfully changed.';
|
|
||||||
})
|
|
||||||
.catch( function() {
|
|
||||||
form.password.$setValidity('mongoose', false);
|
|
||||||
$scope.errors.other = 'Incorrect password';
|
|
||||||
$scope.message = '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,21 +0,0 @@
|
|||||||
div(ng-include='"components/navbar/navbar.html"')
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-sm-12
|
|
||||||
h1 Change Password
|
|
||||||
.col-sm-12
|
|
||||||
form.form(name='form', ng-submit='changePassword(form)', novalidate='')
|
|
||||||
.form-group
|
|
||||||
label Current Password
|
|
||||||
input.form-control(type='password', name='password', ng-model='user.oldPassword', mongoose-error='')
|
|
||||||
p.help-block(ng-show='form.password.$error.mongoose')
|
|
||||||
| {{ errors.other }}
|
|
||||||
.form-group
|
|
||||||
label New Password
|
|
||||||
input.form-control(type='password', name='newPassword', ng-model='user.newPassword', ng-minlength='3', required='')
|
|
||||||
p.help-block(ng-show='(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || submitted)')
|
|
||||||
| Password must be at least 3 characters.
|
|
||||||
|
|
||||||
p.help-block {{ message }}
|
|
||||||
|
|
||||||
button.btn.btn-lg.btn-primary(type='submit') Save changes
|
|
@ -1,37 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('SignupCtrl', function ($scope, Auth, $location, $window) {
|
|
||||||
$scope.user = {};
|
|
||||||
$scope.errors = {};
|
|
||||||
|
|
||||||
$scope.register = function(form) {
|
|
||||||
$scope.submitted = true;
|
|
||||||
|
|
||||||
if(form.$valid) {
|
|
||||||
Auth.createUser({
|
|
||||||
name: $scope.user.name,
|
|
||||||
email: $scope.user.email,
|
|
||||||
password: $scope.user.password
|
|
||||||
})
|
|
||||||
.then( function() {
|
|
||||||
// Account created, redirect to home
|
|
||||||
$location.path('/');
|
|
||||||
})
|
|
||||||
.catch( function(err) {
|
|
||||||
err = err.data;
|
|
||||||
$scope.errors = {};
|
|
||||||
|
|
||||||
// Update validity of form fields that match the mongoose errors
|
|
||||||
angular.forEach(err.errors, function(error, field) {
|
|
||||||
form[field].$setValidity('mongoose', false);
|
|
||||||
$scope.errors[field] = error.message;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.loginOauth = function(provider) {
|
|
||||||
$window.location.href = '/auth/' + provider;
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,57 +0,0 @@
|
|||||||
div(ng-include='"components/navbar/navbar.html"')
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-sm-12
|
|
||||||
h1 Sign up
|
|
||||||
.col-sm-12
|
|
||||||
form.form(name='form', ng-submit='register(form)', novalidate='')
|
|
||||||
.form-group(ng-class='{ "has-success": form.name.$valid && submitted,\
|
|
||||||
"has-error": form.name.$invalid && submitted }')
|
|
||||||
label Name
|
|
||||||
input.form-control(type='text', name='name', ng-model='user.name', required='')
|
|
||||||
p.help-block(ng-show='form.name.$error.required && submitted')
|
|
||||||
| A name is required
|
|
||||||
|
|
||||||
.form-group(ng-class='{ "has-success": form.email.$valid && submitted,\
|
|
||||||
"has-error": form.email.$invalid && submitted }')
|
|
||||||
label Email
|
|
||||||
input.form-control(type='email', name='email', ng-model='user.email', required='', mongoose-error='')
|
|
||||||
p.help-block(ng-show='form.email.$error.email && submitted')
|
|
||||||
| Doesn't look like a valid email.
|
|
||||||
p.help-block(ng-show='form.email.$error.required && submitted')
|
|
||||||
| What's your email address?
|
|
||||||
p.help-block(ng-show='form.email.$error.mongoose')
|
|
||||||
| {{ errors.email }}
|
|
||||||
|
|
||||||
.form-group(ng-class='{ "has-success": form.password.$valid && submitted,\
|
|
||||||
"has-error": form.password.$invalid && submitted }')
|
|
||||||
label Password
|
|
||||||
input.form-control(type='password', name='password', ng-model='user.password', ng-minlength='3', required='', mongoose-error='')
|
|
||||||
p.help-block(ng-show='(form.password.$error.minlength || form.password.$error.required) && submitted')
|
|
||||||
| Password must be at least 3 characters.
|
|
||||||
p.help-block(ng-show='form.password.$error.mongoose')
|
|
||||||
| {{ errors.password }}
|
|
||||||
|
|
||||||
div
|
|
||||||
button.btn.btn-inverse.btn-lg.btn-login(type='submit')
|
|
||||||
| Sign up
|
|
||||||
= ' '
|
|
||||||
a.btn.btn-default.btn-lg.btn-register(href='/login')
|
|
||||||
| Login
|
|
||||||
|
|
||||||
|
|
||||||
hr
|
|
||||||
|
|
||||||
div
|
|
||||||
a.btn.btn-facebook(href='', ng-click='loginOauth("facebook")')
|
|
||||||
i.fa.fa-facebook
|
|
||||||
| Connect with Facebook
|
|
||||||
= ' '
|
|
||||||
a.btn.btn-google-plus(href='', ng-click='loginOauth("google")')
|
|
||||||
i.fa.fa-google-plus
|
|
||||||
| Connect with Google+
|
|
||||||
= ' '
|
|
||||||
a.btn.btn-twitter(href='', ng-click='loginOauth("twitter")')
|
|
||||||
i.fa.fa-twitter
|
|
||||||
| Connect with Twitter
|
|
||||||
hr
|
|
@ -1,17 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('AdminCtrl', function ($scope, $http, Auth, User) {
|
|
||||||
|
|
||||||
// Use the User $resource to fetch all users
|
|
||||||
$scope.users = User.query();
|
|
||||||
|
|
||||||
$scope.delete = function(user) {
|
|
||||||
User.remove({ id: user._id });
|
|
||||||
angular.forEach($scope.users, function(u, i) {
|
|
||||||
if (u === user) {
|
|
||||||
$scope.users.splice(i, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,11 +0,0 @@
|
|||||||
div(ng-include='"components/navbar/navbar.html"')
|
|
||||||
.container
|
|
||||||
p
|
|
||||||
| The delete user and user index api routes are restricted to users with the 'admin' role.
|
|
||||||
ul.list-group
|
|
||||||
li.list-group-item(ng-repeat='user in users')
|
|
||||||
strong {{user.name}}
|
|
||||||
br
|
|
||||||
span.text-muted {{user.email}}
|
|
||||||
a.trash(ng-click='delete(user)')
|
|
||||||
span.glyphicon.glyphicon-trash.pull-right
|
|
@ -1,10 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.config(function ($routeProvider) {
|
|
||||||
$routeProvider
|
|
||||||
.when('/admin', {
|
|
||||||
templateUrl: 'app/admin/admin.html',
|
|
||||||
controller: 'AdminCtrl'
|
|
||||||
});
|
|
||||||
});
|
|
@ -1 +0,0 @@
|
|||||||
.trash { color:rgb(209, 91, 71); }
|
|
@ -15,42 +15,4 @@ angular.module('markdownFormatWdiffApp', [
|
|||||||
});
|
});
|
||||||
|
|
||||||
$locationProvider.html5Mode(true);
|
$locationProvider.html5Mode(true);
|
||||||
$httpProvider.interceptors.push('authInterceptor');
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.factory('authInterceptor', function ($rootScope, $q, $cookieStore, $location) {
|
|
||||||
return {
|
|
||||||
// Add authorization token to headers
|
|
||||||
request: function (config) {
|
|
||||||
config.headers = config.headers || {};
|
|
||||||
if ($cookieStore.get('token')) {
|
|
||||||
config.headers.Authorization = 'Bearer ' + $cookieStore.get('token');
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Intercept 401s and redirect you to login
|
|
||||||
responseError: function(response) {
|
|
||||||
if(response.status === 401) {
|
|
||||||
$location.path('/login');
|
|
||||||
// remove any stale tokens
|
|
||||||
$cookieStore.remove('token');
|
|
||||||
return $q.reject(response);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return $q.reject(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
.run(function ($rootScope, $location, Auth) {
|
|
||||||
// Redirect to login if route requires auth and you're not logged in
|
|
||||||
$rootScope.$on('$routeChangeStart', function (event, next) {
|
|
||||||
Auth.isLoggedInAsync(function(loggedIn) {
|
|
||||||
if (next.authenticate && !loggedIn) {
|
|
||||||
$location.path('/login');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
@ -8,6 +8,14 @@ $fa-font-path: "/bower_components/font-awesome/fonts";
|
|||||||
* App-wide Styles
|
* App-wide Styles
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.hero-unit {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-unit h1 a {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
.browsehappy {
|
.browsehappy {
|
||||||
margin: 0.2em 0;
|
margin: 0.2em 0;
|
||||||
background: #ccc;
|
background: #ccc;
|
||||||
@ -41,10 +49,6 @@ form.form-inline.controls > .form-group > label, {
|
|||||||
|
|
||||||
// Component styles are injected through grunt
|
// Component styles are injected through grunt
|
||||||
// injector
|
// injector
|
||||||
@import 'account/login/login.scss';
|
@import 'compare/compare.scss';
|
||||||
@import 'admin/admin.scss';
|
|
||||||
@import 'document/document.scss';
|
|
||||||
@import 'document/revision-new/revision-new.scss';
|
|
||||||
@import 'wdiff/wdiff.scss';
|
|
||||||
@import 'modal/modal.scss';
|
@import 'modal/modal.scss';
|
||||||
// endinjector
|
// endinjector
|
14
client/app/compare/compare.js
Normal file
14
client/app/compare/compare.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('markdownFormatWdiffApp')
|
||||||
|
.config(function ($routeProvider) {
|
||||||
|
$routeProvider
|
||||||
|
.when('/', {
|
||||||
|
templateUrl: 'app/compare/create/create.html',
|
||||||
|
controller: 'CompareCreateCtrl'
|
||||||
|
})
|
||||||
|
.when('/:id', {
|
||||||
|
templateUrl: 'app/compare/show/show.html',
|
||||||
|
controller: 'CompareShowCtrl'
|
||||||
|
});
|
||||||
|
});
|
22
client/app/compare/create/create.controller.js
Normal file
22
client/app/compare/create/create.controller.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('markdownFormatWdiffApp')
|
||||||
|
.controller('CompareCreateCtrl', function ($scope, $http, $location) {
|
||||||
|
$scope.docA = "";
|
||||||
|
$scope.docB = "";
|
||||||
|
$scope.wdiff = "";
|
||||||
|
$scope.wdiffMarkdown = "";
|
||||||
|
$scope.displayAsMarkdown = true;
|
||||||
|
|
||||||
|
$scope.compare = function() {
|
||||||
|
$http.post('/api/compare',
|
||||||
|
{ a: $scope.docA, b: $scope.docB },
|
||||||
|
{headers:{"Content-Type":"application/json"}})
|
||||||
|
.success(function (comparison) {
|
||||||
|
$location.path('/'+comparison._id)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})
|
24
client/app/compare/create/create.jade
Normal file
24
client/app/compare/create/create.jade
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// nav(ng-include='"components/navbar/navbar.html"')
|
||||||
|
|
||||||
|
nav(ng-include='"components/elements/header.html"', onload='title = "wdiff markdown"; ')
|
||||||
|
|
||||||
|
.container
|
||||||
|
|
||||||
|
form.row
|
||||||
|
|
||||||
|
.col-md-2.col-sm-12.form-group
|
||||||
|
.controls.well
|
||||||
|
a.btn.btn-block.btn-primary(type='button', ng-click='compare()') compare
|
||||||
|
|
||||||
|
.col-lg-5.col-sm-12.form-group
|
||||||
|
label(for='docA')
|
||||||
|
| Original
|
||||||
|
textarea.form-control(id='docA', ng-model='docA')
|
||||||
|
|
||||||
|
.col-lg-5.col-sm-12.form-group
|
||||||
|
label(for='docB')
|
||||||
|
| Final
|
||||||
|
textarea.form-control(id='docB', ng-model='docB')
|
||||||
|
|
||||||
|
|
||||||
|
footer(ng-include='"components/elements/footer.html"')
|
35
client/app/compare/show/show.controller.js
Normal file
35
client/app/compare/show/show.controller.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('markdownFormatWdiffApp')
|
||||||
|
.controller('CompareShowCtrl', function ($scope, $routeParams, $http) {
|
||||||
|
$scope.wdiff = {};
|
||||||
|
$scope.before = {};
|
||||||
|
$scope.after = {};
|
||||||
|
$scope.isShowWdiff = true;
|
||||||
|
|
||||||
|
|
||||||
|
// if routeParams specifies a user, restrict the query to that user
|
||||||
|
var path = '/api/compare/wdiff/' + $routeParams.id;
|
||||||
|
$http.get(path).success(function(comparison) {
|
||||||
|
$scope.wdiff = comparison.wdiff;
|
||||||
|
$scope.before = comparison.a;
|
||||||
|
$scope.after = comparison.b;
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.showBefore = function() {
|
||||||
|
$scope.isShowBefore = true;
|
||||||
|
$scope.isShowAfter = false;
|
||||||
|
$scope.isShowWdiff = false;
|
||||||
|
}
|
||||||
|
$scope.showAfter = function() {
|
||||||
|
$scope.isShowBefore = false;
|
||||||
|
$scope.isShowAfter = true;
|
||||||
|
$scope.isShowWdiff = false;
|
||||||
|
}
|
||||||
|
$scope.showWdiff = function() {
|
||||||
|
$scope.isShowBefore = false;
|
||||||
|
$scope.isShowAfter = false;
|
||||||
|
$scope.isShowWdiff = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
28
client/app/compare/show/show.jade
Normal file
28
client/app/compare/show/show.jade
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// nav(ng-include='"components/navbar/navbar.html"')
|
||||||
|
|
||||||
|
nav(ng-include='"components/elements/header.html"', onload='title = "wdiff markdown"; subtitle ="results"')
|
||||||
|
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-md-2.col-sm-12
|
||||||
|
.controls.well.btn-group
|
||||||
|
a.btn.btn-block.btn-primary(ng-class='{"active": isShowBefore}', type='submit', ng-click='showBefore()')
|
||||||
|
| Original
|
||||||
|
a.btn.btn-block.btn-primary(ng-class='{"active": isShowAfter}', type='submit', ng-click='showAfter()')
|
||||||
|
| Final
|
||||||
|
a.btn.btn-block.btn-primary(ng-class='{"active": isShowWdiff}', type='submit', ng-click='showWdiff()')
|
||||||
|
| Difference
|
||||||
|
|
||||||
|
.col-md-10.col-sm-12.well(ng-show='isShowBefore')
|
||||||
|
div(btf-markdown='before')
|
||||||
|
|
||||||
|
|
||||||
|
.col-md-10.col-sm-12.well(ng-show='isShowWdiff')
|
||||||
|
div(btf-markdown='wdiff')
|
||||||
|
|
||||||
|
.col-md-10.col-sm-12.well(ng-show='isShowAfter')
|
||||||
|
div(btf-markdown='after')
|
||||||
|
//pre
|
||||||
|
{{json(result)}}
|
||||||
|
|
||||||
|
footer(ng-include='"components/elements/footer.html"')
|
@ -1,109 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.config(function ($routeProvider) {
|
|
||||||
$routeProvider
|
|
||||||
.when('/', {
|
|
||||||
templateUrl: 'app/document/index/index.html',
|
|
||||||
controller: 'DocumentIndexCtrl'
|
|
||||||
})
|
|
||||||
.when('/user/:userid', {
|
|
||||||
templateUrl: 'app/document/index/index.html',
|
|
||||||
controller: 'DocumentIndexCtrl'
|
|
||||||
})
|
|
||||||
.when('/:id', {
|
|
||||||
templateUrl: 'app/document/show/show.html',
|
|
||||||
controller: 'DocumentShowCtrl'
|
|
||||||
})
|
|
||||||
.when('/:id/revision/new', {
|
|
||||||
templateUrl: 'app/document/revision-new/revision-new.html',
|
|
||||||
controller: 'DocumentRevisionNewCtrl'
|
|
||||||
})
|
|
||||||
.when('/:id/revision/:revisionid', {
|
|
||||||
templateUrl: 'app/document/revision/revision.html',
|
|
||||||
controller: 'DocumentRevisionCtrl'
|
|
||||||
})
|
|
||||||
.when('/wdiff/:revisionida/:revisionidb', {
|
|
||||||
templateUrl: 'app/document/wdiff/wdiff.html',
|
|
||||||
controller: 'DocumentWdiffCtrl'
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
.factory('App', function ($window, Auth) {
|
|
||||||
var root = {};
|
|
||||||
|
|
||||||
root.json = function (object) {
|
|
||||||
return JSON.stringify(object, null, " ");
|
|
||||||
};
|
|
||||||
|
|
||||||
//returns true if this revision is the current revision in its document
|
|
||||||
root.isCurrent = function (document, revision) {
|
|
||||||
if (!revision)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var cr = document.currentRevision;
|
|
||||||
var compareId = (cr.hasOwnProperty('_id') ? cr._id : cr);
|
|
||||||
return revision._id == compareId;
|
|
||||||
};
|
|
||||||
|
|
||||||
//returns true if this revision is the first revision in its document
|
|
||||||
// Note: documents have an initial empty sentinel revision - that is the zeroth revision
|
|
||||||
root.isFirst = function (document, revision) {
|
|
||||||
if (!revision)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (document.revisions.length <= 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var fr = document.revisions[1];
|
|
||||||
var compareId = (fr.hasOwnProperty('_id') ? fr._id : fr);
|
|
||||||
return revision._id == compareId;
|
|
||||||
};
|
|
||||||
|
|
||||||
//returns true if the current user is logged in and is the owner of this document / revision
|
|
||||||
root.isOwner = function (document) {
|
|
||||||
var currentUser = Auth.getCurrentUser();
|
|
||||||
if (!currentUser || !document || !document.owner)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return document.owner._id == currentUser._id;
|
|
||||||
}
|
|
||||||
|
|
||||||
//looks up this revision in the document revisions list
|
|
||||||
//and returns the previous revision
|
|
||||||
//if this is the oldest revision, then just return itself
|
|
||||||
root.previousRevision = function (document, revision) {
|
|
||||||
//sometimes the document will have revision ids as a separate field and sometimes it wont
|
|
||||||
var revisionIds = document.revisions;
|
|
||||||
if (revisionIds[0].hasOwnProperty('_id'))
|
|
||||||
revisionIds = _.pluck(revisionIds, '_id');
|
|
||||||
|
|
||||||
//find the index of the revision in documents
|
|
||||||
var index = _.findIndex(revisionIds);
|
|
||||||
var prevIndex = index-1;
|
|
||||||
if (prevIndex < 0)
|
|
||||||
prevIndex = 0;
|
|
||||||
|
|
||||||
return {_id: revisionIds[prevIndex]};
|
|
||||||
}
|
|
||||||
//looks up this revision in the document revisions list
|
|
||||||
//and returns the previous revision
|
|
||||||
//if this is the oldest revision, then just return itself
|
|
||||||
root.nextRevision = function (document, revision) {
|
|
||||||
//sometimes the document will have revision ids as a separate field and sometimes it wont
|
|
||||||
var revisionIds = document.revisions;
|
|
||||||
if (revisionIds[0].hasOwnProperty('_id'))
|
|
||||||
revisionIds = _.pluck(revisionIds, '_id');
|
|
||||||
|
|
||||||
//find the index of the revision in documents
|
|
||||||
var index = _.findIndex(revisionIds);
|
|
||||||
var nextIndex = index+1;
|
|
||||||
if (nextIndex >= document.revisions.size())
|
|
||||||
nextIndex = document.revisions.size()-1;
|
|
||||||
|
|
||||||
return {_id: revisionIds[nextIndex]};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return root;
|
|
||||||
});
|
|
@ -1,35 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('DocumentIndexCtrl', function ($scope, $routeParams, $http, Auth, $location, App) {
|
|
||||||
$scope.App = App;
|
|
||||||
$scope.title = 'Documents';
|
|
||||||
|
|
||||||
$scope.documents = [];
|
|
||||||
$scope.newDocumentTitle = '';
|
|
||||||
|
|
||||||
$scope.getCurrentUser = Auth.getCurrentUser;
|
|
||||||
$scope.isLoggedIn = Auth.isLoggedIn;
|
|
||||||
|
|
||||||
// if routeParams specifies a user, restrict the query to that user
|
|
||||||
var path = '/api/documents'+ ($routeParams.userid ? '/owner/'+$routeParams.userid : '');
|
|
||||||
$http.get(path).success(function(documents) {
|
|
||||||
$scope.documents = documents;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$scope.createDocument = function () {
|
|
||||||
if ($scope.newDocumentTitle == "")
|
|
||||||
return
|
|
||||||
|
|
||||||
//save the document
|
|
||||||
$http.post('/api/documents', {title: $scope.newDocumentTitle})
|
|
||||||
.success(function(newDocument) {
|
|
||||||
$scope.documents.push(newDocument);
|
|
||||||
//skip redirecting to document view page
|
|
||||||
//$location.path('/'+newDocument._id);
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
})
|
|
@ -1,52 +0,0 @@
|
|||||||
nav(ng-include='"components/navbar/navbar.html"')
|
|
||||||
|
|
||||||
nav(ng-include='"components/elements/header.html"')
|
|
||||||
|
|
||||||
.container
|
|
||||||
.row(ng-show='isLoggedIn()')
|
|
||||||
.col-lg-0.col-md-12
|
|
||||||
form.form-inline.controls.well
|
|
||||||
.form-group
|
|
||||||
label(for='title-input')
|
|
||||||
| New Document
|
|
||||||
input.form-control(type='text', id='title-input', placeholder='title', ng-model='newDocumentTitle')
|
|
||||||
button.btn.btn-default(type='submit', ng-click='createDocument()')
|
|
||||||
| Create
|
|
||||||
|
|
||||||
.row
|
|
||||||
.col-md-6.col-sm-12(ng-repeat='document in documents | orderBy:"currentRevision.created":true' )
|
|
||||||
.center-block
|
|
||||||
h1
|
|
||||||
a(href='/{{document._id}}')
|
|
||||||
| {{document.title}}
|
|
||||||
a.btn.btn-default.pull-right(href='/{{document._id}}/revision/new')
|
|
||||||
| New rev
|
|
||||||
a.btn.btn-default.pull-right(ng-hide='document.revisions.length<=1', href='/wdiff/{{document.revisions[1]._id}}/{{document.currentRevision._id}}')
|
|
||||||
| Wdiff all
|
|
||||||
div.indent
|
|
||||||
p(ng-hide='App.isOwner(document)')
|
|
||||||
span
|
|
||||||
| Owner:
|
|
||||||
span
|
|
||||||
| {{document.owner.name}}
|
|
||||||
table.revisions
|
|
||||||
tr
|
|
||||||
th.state State
|
|
||||||
th.created Revision
|
|
||||||
//th.wdiff(colspan='2') Wdiff With
|
|
||||||
tr(ng-repeat='revision in document.revisions | orderBy:"created":true | limitTo:5' ng-hide='$last')
|
|
||||||
td.state {{revision.state}}
|
|
||||||
td.created
|
|
||||||
h4
|
|
||||||
a(href='/{{document._id}}/revision/{{revision._id}}')
|
|
||||||
{{revision.created}}
|
|
||||||
//these aren't working great
|
|
||||||
//td.wdiff.prev
|
|
||||||
a.btn.btn-default(ng-hide='$last', href='/wdiff/{{App.previousRevision(document, revision)._id}}/{{revision._id}}') Prev
|
|
||||||
//td.wdiff.curr
|
|
||||||
a.btn.btn-default(ng-hide='$first', href='/wdiff/{{revision._id}}/{{document.currentRevision._id}}') Current
|
|
||||||
//pre
|
|
||||||
{{App.json(document)}}
|
|
||||||
|
|
||||||
|
|
||||||
footer(ng-include='"components/elements/footer.html"')
|
|
@ -1,34 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('DocumentRevisionNewCtrl', function ($scope, $routeParams, $http, Auth, $location, App) {
|
|
||||||
$scope.App = App;
|
|
||||||
$scope.title = '';
|
|
||||||
$scope.subtitle = '';
|
|
||||||
|
|
||||||
$scope.revision = {};
|
|
||||||
|
|
||||||
$scope.stateOptions = ['first draft', 'final draft', 'first edit', 'final edit'];
|
|
||||||
|
|
||||||
$scope.getCurrentUser = Auth.getCurrentUser;
|
|
||||||
$scope.isLoggedIn = Auth.isLoggedIn;
|
|
||||||
|
|
||||||
var path = '/api/documents/' + $routeParams.id;
|
|
||||||
$http.get(path).success(function(document) {
|
|
||||||
$scope.document = document;
|
|
||||||
$scope.revision = angular.copy(document.currentRevision);
|
|
||||||
$scope.title = document.title;
|
|
||||||
$scope.subtitle = 'new revision';
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$scope.saveRevision = function() {
|
|
||||||
//save the revision to the document
|
|
||||||
$http.post('/api/documents/'+$routeParams.id+'/revisions', $scope.revision)
|
|
||||||
.success(function(newRevision) {
|
|
||||||
//and redirect to the revision view page
|
|
||||||
$location.path('/'+$routeParams.id+'/revision/'+newRevision._id);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
})
|
|
@ -1,32 +0,0 @@
|
|||||||
nav(ng-include='"components/navbar/navbar.html"')
|
|
||||||
|
|
||||||
nav(ng-include='"components/elements/header.html"')
|
|
||||||
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-lg-6.col-md-12
|
|
||||||
form.controls
|
|
||||||
h4
|
|
||||||
{{document.title}} - {{revision.created}}
|
|
||||||
.form-group
|
|
||||||
label(for='status-input')
|
|
||||||
| Status
|
|
||||||
select.form-control(id='status-input', ng-model='revision.state', ng-options='stateOption as stateOption for stateOption in stateOptions')
|
|
||||||
option(value='{{stateOption}}')
|
|
||||||
//input.form-control(type='text', id='status-input', ng-model='revision.state')
|
|
||||||
.form-group
|
|
||||||
label(for='content-input')
|
|
||||||
| Content
|
|
||||||
textarea.form-control(id='content-input', ng-model='revision.content')
|
|
||||||
button.btn.btn-primary(ng-click='saveRevision()')
|
|
||||||
| Save
|
|
||||||
|
|
||||||
.col-lg-6.col-md-12
|
|
||||||
div(btf-markdown='revision.content')
|
|
||||||
|
|
||||||
//.row
|
|
||||||
pre.col-lg-9.col-md-12.center-block
|
|
||||||
{{json(revision)}}
|
|
||||||
|
|
||||||
|
|
||||||
footer(ng-include='"components/elements/footer.html"')
|
|
@ -1,20 +0,0 @@
|
|||||||
#content-input {
|
|
||||||
resize: vertical;
|
|
||||||
min-height: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media (min-width: $screen-md-min) {
|
|
||||||
#content-input {
|
|
||||||
resize: vertical;
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: $screen-lg-min) {
|
|
||||||
#content-input {
|
|
||||||
resize: vertical;
|
|
||||||
min-height: 450px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('DocumentRevisionCtrl', function ($scope, $routeParams, $http, Auth, App) {
|
|
||||||
$scope.App = App;
|
|
||||||
$scope.revision = {};
|
|
||||||
|
|
||||||
$scope.title = '';
|
|
||||||
$scope.subtitle = '';
|
|
||||||
|
|
||||||
$scope.getCurrentUser = Auth.getCurrentUser;
|
|
||||||
$scope.isLoggedIn = Auth.isLoggedIn;
|
|
||||||
|
|
||||||
//returns true if the current user is logged in and is the owner of this document / revision
|
|
||||||
$scope.isOwner = function () {
|
|
||||||
var currentUser = Auth.getCurrentUser();
|
|
||||||
if (!currentUser || !$scope.revision || !$scope.revision.owner)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return $scope.revision.owner._id == currentUser._id;
|
|
||||||
}
|
|
||||||
|
|
||||||
//returns true if this revision is the current revision in its document
|
|
||||||
$scope.isCurrent = function (revision) {
|
|
||||||
if (!revision)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return revision._id == revision.document.currentRevision;
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = '/api/documents/'+$routeParams.id+'/revisions/' + $routeParams.revisionid;
|
|
||||||
$http.get(path).success(function(revision) {
|
|
||||||
$scope.revision = revision;
|
|
||||||
$scope.title = revision.document.title;
|
|
||||||
$scope.subtitle = $scope.isCurrent() ? " (current)":(" ("+$scope.revision.created+")");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
@ -1,33 +0,0 @@
|
|||||||
nav(ng-include='"components/navbar/navbar.html"')
|
|
||||||
|
|
||||||
nav(ng-include='"components/elements/header.html"')
|
|
||||||
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
//span(ng-show='isCurrent()')
|
|
||||||
| Current revision
|
|
||||||
form.form-inline.controls.well
|
|
||||||
|
|
||||||
//a.btn.btn-primary(ng-hide='App.isFirst(revision.document, revision)' href='/{{revision.document._id}}/revision/{{App.previousRevision(revision.document, revision)._id}}')
|
|
||||||
| View Previous
|
|
||||||
//a.btn.btn-primary(ng-hide='App.isFirst()' href='/wdiff/{{App.previousRevision(revision.document, revision)._id}}/{{revision._id}}')
|
|
||||||
| Wdiff from Previous
|
|
||||||
//a.btn.btn-primary(ng-hide='App.isCurrent()' href='/wdiff/{{revision._id}}/{{App.nextRevision(revision.document, revision)._id}}')
|
|
||||||
| Wdiff to Next
|
|
||||||
//a.btn.btn-primary(ng-hide='App.isCurrent(revision.document, revision)' href='/{{revision.document._id}}/revision/{{App.nextRevision(revision.document, revision)._id}}')
|
|
||||||
| View Next
|
|
||||||
a.btn.btn-primary.pull-right(ng-hide='App.isCurrent(revision.document, revision)' href='/wdiff/{{revision._id}}/{{revision.document.currentRevision}}')
|
|
||||||
| Wdiff to Current
|
|
||||||
|
|
||||||
.row
|
|
||||||
.col-lg-6.col-md-9
|
|
||||||
div
|
|
||||||
p
|
|
||||||
| State:
|
|
||||||
{{revision.state}}
|
|
||||||
div(btf-markdown='revision.content')
|
|
||||||
//pre
|
|
||||||
{{json(revision)}}
|
|
||||||
|
|
||||||
|
|
||||||
footer(ng-include='"components/elements/footer.html"')
|
|
@ -1,40 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('DocumentShowCtrl', function ($scope, $routeParams, $http, Auth, App) {
|
|
||||||
$scope.App = App;
|
|
||||||
$scope.document = {};
|
|
||||||
$scope.title = '';
|
|
||||||
|
|
||||||
$scope.getCurrentUser = Auth.getCurrentUser;
|
|
||||||
$scope.isLoggedIn = Auth.isLoggedIn;
|
|
||||||
|
|
||||||
$scope.isOwner = function () {
|
|
||||||
var currentUser = Auth.getCurrentUser();
|
|
||||||
if (!currentUser || !$scope.document || !$scope.document.owner)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return $scope.document.owner._id == currentUser._id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if routeParams specifies a user, restrict the query to that user
|
|
||||||
var path = '/api/documents/' + $routeParams.id;
|
|
||||||
$http.get(path).success(function(document) {
|
|
||||||
$scope.document = document;
|
|
||||||
$scope.title = document.title;
|
|
||||||
});
|
|
||||||
|
|
||||||
//looks up this revision in the document revisions list
|
|
||||||
//and returns the previous revision
|
|
||||||
//if this is the oldest revision, then just return itself
|
|
||||||
$scope.previousRevision = function (revision) {
|
|
||||||
//find the index of the revision in documents
|
|
||||||
var index = _.findIndex($scope.document.revisions, '_id');
|
|
||||||
var prevIndex = index-1;
|
|
||||||
if (prevIndex < 0)
|
|
||||||
prevIndex = 0;
|
|
||||||
|
|
||||||
return $scope.document.revisions[prevIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
@ -1,39 +0,0 @@
|
|||||||
nav(ng-include='"components/navbar/navbar.html"')
|
|
||||||
|
|
||||||
nav(ng-include='"components/elements/header.html"')
|
|
||||||
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-lg-12
|
|
||||||
|
|
||||||
|
|
||||||
.row
|
|
||||||
.col-lg-6.col-sm-12
|
|
||||||
form.form-inline.controls.well(ng-show='App.isOwner(document)')
|
|
||||||
a.btn.btn-primary(href='/{{document._id}}/revision/new')
|
|
||||||
| New Revision
|
|
||||||
|
|
||||||
table.revisions
|
|
||||||
tr
|
|
||||||
th.state State
|
|
||||||
th.created Revision
|
|
||||||
tr(ng-repeat='revision in document.revisions | orderBy:"created":true' ng-hide='$last' )
|
|
||||||
td.state {{revision.state}}
|
|
||||||
td.created
|
|
||||||
h4
|
|
||||||
a(href='/{{document._id}}/revision/{{revision._id}}')
|
|
||||||
{{revision.created}}
|
|
||||||
//these aren't working great
|
|
||||||
//td.wdiff.prev
|
|
||||||
a.btn.btn-default(ng-hide='$last', href='/wdiff/{{App.previousRevision(document, revision)._id}}/{{revision._id}}') Prev
|
|
||||||
//td.wdiff.curr
|
|
||||||
a.btn.btn-default(ng-hide='$first', href='/wdiff/{{revision._id}}/{{document.currentRevision._id}}') Current
|
|
||||||
|
|
||||||
.col-lg-6.col-sm-12
|
|
||||||
div(btf-markdown='document.currentRevision.content')
|
|
||||||
|
|
||||||
//pre.col-lg-6
|
|
||||||
| {{json(document)}}
|
|
||||||
|
|
||||||
|
|
||||||
footer(ng-include='"components/elements/footer.html"')
|
|
@ -1,38 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('DocumentWdiffCtrl', function ($scope, $routeParams, $http, Auth, App) {
|
|
||||||
$scope.App = App;
|
|
||||||
$scope.wdiff = '';
|
|
||||||
$scope.title = '';
|
|
||||||
$scope.same = false;
|
|
||||||
$scope.revisionA = {};
|
|
||||||
$scope.revisionB = {};
|
|
||||||
$scope.isShowBefore = true;
|
|
||||||
$scope.isShowAfter = false;
|
|
||||||
|
|
||||||
$scope.getCurrentUser = Auth.getCurrentUser;
|
|
||||||
$scope.isLoggedIn = Auth.isLoggedIn;
|
|
||||||
|
|
||||||
|
|
||||||
var path = '/api/documents/wdiff/'+$routeParams.revisionida+'/'+$routeParams.revisionidb;
|
|
||||||
$http.get(path).success(function(result) {
|
|
||||||
$scope.result = result;
|
|
||||||
$scope.wdiff = result.wdiff;
|
|
||||||
$scope.revisionA = result.a;
|
|
||||||
$scope.revisionB = result.b;
|
|
||||||
|
|
||||||
$scope.title = result.a.document.title;
|
|
||||||
$scope.subtitle = "wdiff: "+result.a.created + " / " + result.b.created;
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.showBefore = function() {
|
|
||||||
$scope.isShowBefore = true;
|
|
||||||
$scope.isShowAfter = false;
|
|
||||||
}
|
|
||||||
$scope.showAfter = function() {
|
|
||||||
$scope.isShowBefore = false;
|
|
||||||
$scope.isShowAfter = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
@ -1,23 +0,0 @@
|
|||||||
wdiff.jadenav(ng-include='"components/navbar/navbar.html"')
|
|
||||||
|
|
||||||
nav(ng-include='"components/elements/header.html"')
|
|
||||||
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-md-6.col-sm-12.well(ng-show='isShowBefore')
|
|
||||||
div(btf-markdown='revisionA.content')
|
|
||||||
.col-md-6.col-sm-12
|
|
||||||
.controls.well
|
|
||||||
a.btn.btn-default.pull-left(ng-hide='isShowBefore', type='submit', ng-click='showBefore()')
|
|
||||||
| Show Before
|
|
||||||
a.btn.btn-default.pull-right(ng-hide='isShowAfter', type='submit', ng-click='showAfter()')
|
|
||||||
| Show After
|
|
||||||
|
|
||||||
div(btf-markdown='wdiff')
|
|
||||||
.col-md-6.col-sm-12.well(ng-show='isShowAfter')
|
|
||||||
div(btf-markdown='revisionB.content')
|
|
||||||
//pre
|
|
||||||
{{json(result)}}
|
|
||||||
|
|
||||||
|
|
||||||
footer(ng-include='"components/elements/footer.html"')
|
|
@ -1,44 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.controller('WdiffCtrl', function ($scope, $http) {
|
|
||||||
$scope.docA = "";
|
|
||||||
$scope.docB = "";
|
|
||||||
$scope.wdiff = "";
|
|
||||||
$scope.wdiffMarkdown = "";
|
|
||||||
$scope.displayAsMarkdown = true;
|
|
||||||
|
|
||||||
$scope.compare = function() {
|
|
||||||
$http.post('/api/wdiff'+($scope.displayAsMarkdown ? '/markdown': ''),
|
|
||||||
{ a: $scope.docA, b: $scope.docB },
|
|
||||||
{headers:{"Content-Type":"application/json"}})
|
|
||||||
.success(function (data) {
|
|
||||||
if ($scope.displayAsMarkdown) {
|
|
||||||
|
|
||||||
$scope.wdiffMarkdown = data.markdown; //data.markdown;
|
|
||||||
$scope.wdiff = '';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
$scope.wdiff = data.wdiff;
|
|
||||||
$scope.wdiffMarkdown = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/* courtesy some rando (doesn't work):
|
|
||||||
function expandTextarea(id) {
|
|
||||||
var element = document.getElementById(id);
|
|
||||||
|
|
||||||
element.addEventListener('keyup', function() {
|
|
||||||
this.style.overflow = 'hidden';
|
|
||||||
this.style.height = 0;
|
|
||||||
this.style.height = this.scrollHeight + 'px';
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
expandTextarea('docA');
|
|
||||||
expandTextarea('docB');
|
|
||||||
*/
|
|
||||||
|
|
||||||
})
|
|
@ -1,44 +0,0 @@
|
|||||||
nav(ng-include='"components/navbar/navbar.html"')
|
|
||||||
|
|
||||||
nav(ng-include='"components/elements/header.html"', onload='title = "wdiff"')
|
|
||||||
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-lg-3.col-sm-12
|
|
||||||
.col-lg-6.col-sm-12
|
|
||||||
div.diff-container
|
|
||||||
div(ng-bind='wdiff')
|
|
||||||
.col-lg-3.col-sm-12
|
|
||||||
|
|
||||||
.row
|
|
||||||
.col-lg-3.col-sm-12
|
|
||||||
.col-lg-6.col-sm-12
|
|
||||||
div.diff-container
|
|
||||||
div(btf-markdown='wdiffMarkdown')
|
|
||||||
.col-lg-3.col-sm-12
|
|
||||||
|
|
||||||
hr
|
|
||||||
|
|
||||||
form.row
|
|
||||||
.col-lg-12.form-group
|
|
||||||
div.checkbox
|
|
||||||
label
|
|
||||||
input(type='checkbox', ng-model='displayAsMarkdown')
|
|
||||||
| Display as Markdown
|
|
||||||
|
|
||||||
.col-lg-12.form-group
|
|
||||||
div.btn-group.btn-group-justified(role='group')
|
|
||||||
a.btn.btn-primary(type='button', ng-click='compare()') compare
|
|
||||||
|
|
||||||
.col-lg-6.col-sm-12.form-group
|
|
||||||
label(for='docA')
|
|
||||||
| Document A
|
|
||||||
textarea.form-control(id='docA', ng-model='docA')
|
|
||||||
|
|
||||||
.col-lg-6.col-sm-12.form-group
|
|
||||||
label(for='docB')
|
|
||||||
| Document B
|
|
||||||
textarea.form-control(id='docB', ng-model='docB')
|
|
||||||
|
|
||||||
|
|
||||||
footer(ng-include='"components/elements/footer.html"')
|
|
@ -1,10 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.config(function ($routeProvider) {
|
|
||||||
$routeProvider
|
|
||||||
.when('/test/wdiff', {
|
|
||||||
templateUrl: 'app/wdiff/wdiff.html',
|
|
||||||
controller: 'WdiffCtrl'
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,146 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.factory('Auth', function Auth($location, $rootScope, $http, User, $cookieStore, $q) {
|
|
||||||
var currentUser = {};
|
|
||||||
if($cookieStore.get('token')) {
|
|
||||||
currentUser = User.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate user and save token
|
|
||||||
*
|
|
||||||
* @param {Object} user - login info
|
|
||||||
* @param {Function} callback - optional
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
login: function(user, callback) {
|
|
||||||
var cb = callback || angular.noop;
|
|
||||||
var deferred = $q.defer();
|
|
||||||
|
|
||||||
$http.post('/auth/local', {
|
|
||||||
email: user.email,
|
|
||||||
password: user.password
|
|
||||||
}).
|
|
||||||
success(function(data) {
|
|
||||||
$cookieStore.put('token', data.token);
|
|
||||||
currentUser = User.get();
|
|
||||||
deferred.resolve(data);
|
|
||||||
return cb();
|
|
||||||
}).
|
|
||||||
error(function(err) {
|
|
||||||
this.logout();
|
|
||||||
deferred.reject(err);
|
|
||||||
return cb(err);
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete access token and user info
|
|
||||||
*
|
|
||||||
* @param {Function}
|
|
||||||
*/
|
|
||||||
logout: function() {
|
|
||||||
$cookieStore.remove('token');
|
|
||||||
currentUser = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new user
|
|
||||||
*
|
|
||||||
* @param {Object} user - user info
|
|
||||||
* @param {Function} callback - optional
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
createUser: function(user, callback) {
|
|
||||||
var cb = callback || angular.noop;
|
|
||||||
|
|
||||||
return User.save(user,
|
|
||||||
function(data) {
|
|
||||||
$cookieStore.put('token', data.token);
|
|
||||||
currentUser = User.get();
|
|
||||||
return cb(user);
|
|
||||||
},
|
|
||||||
function(err) {
|
|
||||||
this.logout();
|
|
||||||
return cb(err);
|
|
||||||
}.bind(this)).$promise;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change password
|
|
||||||
*
|
|
||||||
* @param {String} oldPassword
|
|
||||||
* @param {String} newPassword
|
|
||||||
* @param {Function} callback - optional
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
changePassword: function(oldPassword, newPassword, callback) {
|
|
||||||
var cb = callback || angular.noop;
|
|
||||||
|
|
||||||
return User.changePassword({ id: currentUser._id }, {
|
|
||||||
oldPassword: oldPassword,
|
|
||||||
newPassword: newPassword
|
|
||||||
}, function(user) {
|
|
||||||
return cb(user);
|
|
||||||
}, function(err) {
|
|
||||||
return cb(err);
|
|
||||||
}).$promise;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all available info on authenticated user
|
|
||||||
*
|
|
||||||
* @return {Object} user
|
|
||||||
*/
|
|
||||||
getCurrentUser: function() {
|
|
||||||
return currentUser;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a user is logged in
|
|
||||||
*
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
isLoggedIn: function() {
|
|
||||||
return currentUser.hasOwnProperty('role');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for currentUser to resolve before checking if user is logged in
|
|
||||||
*/
|
|
||||||
isLoggedInAsync: function(cb) {
|
|
||||||
if(currentUser.hasOwnProperty('$promise')) {
|
|
||||||
currentUser.$promise.then(function() {
|
|
||||||
cb(true);
|
|
||||||
}).catch(function() {
|
|
||||||
cb(false);
|
|
||||||
});
|
|
||||||
} else if(currentUser.hasOwnProperty('role')) {
|
|
||||||
cb(true);
|
|
||||||
} else {
|
|
||||||
cb(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a user is an admin
|
|
||||||
*
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
isAdmin: function() {
|
|
||||||
return currentUser.role === 'admin';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get auth token
|
|
||||||
*/
|
|
||||||
getToken: function() {
|
|
||||||
return $cookieStore.get('token');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,22 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
|
||||||
.factory('User', function ($resource) {
|
|
||||||
return $resource('/api/users/:id/:controller', {
|
|
||||||
id: '@_id'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
changePassword: {
|
|
||||||
method: 'PUT',
|
|
||||||
params: {
|
|
||||||
controller:'password'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
get: {
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
id:'me'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,8 +1,8 @@
|
|||||||
div.footer
|
div.footer
|
||||||
.container
|
.container
|
||||||
p
|
p
|
||||||
a(href='https://madanworb.com') Adam Brown
|
a(href='https://adamarthurryan.com') Adam Brown
|
||||||
= ' | '
|
= ' | '
|
||||||
| This website is
|
= 'This website is '
|
||||||
a(href='https://github.com/adamarthurryan/wdiff-markdown-editor') open source
|
a(href='https://github.com/adamarthurryan/wdiff-markdown-editor') open source
|
||||||
| .
|
| .
|
@ -1,4 +1,6 @@
|
|||||||
header#banner.hero-unit
|
header#banner.hero-unit
|
||||||
.container
|
.container
|
||||||
h1 {{title}}
|
h1
|
||||||
|
a(href='/')
|
||||||
|
| {{title}}
|
||||||
h3 {{subtitle}}
|
h3 {{subtitle}}
|
@ -1,13 +1,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('markdownFormatWdiffApp')
|
angular.module('markdownFormatWdiffApp')
|
||||||
.controller('NavbarCtrl', function ($scope, $location, Auth) {
|
.controller('NavbarCtrl', function ($scope, $location , /*Auth*/) {
|
||||||
$scope.menu = [{
|
$scope.menu = [{
|
||||||
'title': 'Home',
|
'title': 'Home',
|
||||||
'link': '/'
|
'link': '/'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
$scope.isCollapsed = true;
|
$scope.isCollapsed = true;
|
||||||
|
|
||||||
|
/*
|
||||||
$scope.isLoggedIn = Auth.isLoggedIn;
|
$scope.isLoggedIn = Auth.isLoggedIn;
|
||||||
$scope.isAdmin = Auth.isAdmin;
|
$scope.isAdmin = Auth.isAdmin;
|
||||||
$scope.getCurrentUser = Auth.getCurrentUser;
|
$scope.getCurrentUser = Auth.getCurrentUser;
|
||||||
@ -16,6 +18,7 @@ angular.module('markdownFormatWdiffApp')
|
|||||||
Auth.logout();
|
Auth.logout();
|
||||||
$location.path('/login');
|
$location.path('/login');
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
$scope.isActive = function(route) {
|
$scope.isActive = function(route) {
|
||||||
return route === $location.path();
|
return route === $location.path();
|
||||||
|
@ -62,22 +62,9 @@
|
|||||||
<!-- build:js({.tmp,client}) app/app.js -->
|
<!-- build:js({.tmp,client}) app/app.js -->
|
||||||
<script src="app/app.js"></script>
|
<script src="app/app.js"></script>
|
||||||
<!-- injector:js -->
|
<!-- injector:js -->
|
||||||
<script src="app/account/account.js"></script>
|
<script src="app/compare/compare.js"></script>
|
||||||
<script src="app/account/login/login.controller.js"></script>
|
<script src="app/compare/create/create.controller.js"></script>
|
||||||
<script src="app/account/settings/settings.controller.js"></script>
|
<script src="app/compare/show/show.controller.js"></script>
|
||||||
<script src="app/account/signup/signup.controller.js"></script>
|
|
||||||
<script src="app/admin/admin.controller.js"></script>
|
|
||||||
<script src="app/admin/admin.js"></script>
|
|
||||||
<script src="app/document/document.js"></script>
|
|
||||||
<script src="app/document/index/index.controller.js"></script>
|
|
||||||
<script src="app/document/revision-new/revision-new.controller.js"></script>
|
|
||||||
<script src="app/document/revision/revision.controller.js"></script>
|
|
||||||
<script src="app/document/show/show.controller.js"></script>
|
|
||||||
<script src="app/document/wdiff/wdiff.controller.js"></script>
|
|
||||||
<script src="app/wdiff/wdiff.controller.js"></script>
|
|
||||||
<script src="app/wdiff/wdiff.js"></script>
|
|
||||||
<script src="components/auth/auth.service.js"></script>
|
|
||||||
<script src="components/auth/user.service.js"></script>
|
|
||||||
<script src="components/modal/modal.service.js"></script>
|
<script src="components/modal/modal.service.js"></script>
|
||||||
<script src="components/mongoose-error/mongoose-error.directive.js"></script>
|
<script src="components/mongoose-error/mongoose-error.directive.js"></script>
|
||||||
<script src="components/navbar/navbar.controller.js"></script>
|
<script src="components/navbar/navbar.controller.js"></script>
|
||||||
|
57
server/api/comparison/comparison.controller.js
Normal file
57
server/api/comparison/comparison.controller.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('lodash');
|
||||||
|
var Comparison = require('./comparison.model');
|
||||||
|
var wdiff = require('../../components/wdiff');
|
||||||
|
var mongoose = require('mongoose');
|
||||||
|
|
||||||
|
|
||||||
|
//return the comparison given an id, if it exsits
|
||||||
|
exports.showComparison = function showComparison(req, res) {
|
||||||
|
Comparison.findById(req.params.id).exec(function (err, comparison) {
|
||||||
|
if(err) { return handleError(res, err); }
|
||||||
|
if(!comparison) { return res.send(404); }
|
||||||
|
return res.json(comparison);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//return a markdown wdiff for the comparison given an id, if it exsits
|
||||||
|
exports.wdiffMarkdownComparison = function wdiffMarkdownComparison(req, res) {
|
||||||
|
Comparison.findById(req.params.id).exec(function (err, comparison) {
|
||||||
|
if(err) { return handleError(res, err); }
|
||||||
|
if(!comparison) { return res.send(404); }
|
||||||
|
|
||||||
|
wdiff(comparison.a,comparison.b, true, function(err, result) {
|
||||||
|
if (err)
|
||||||
|
return handleError(res, err);
|
||||||
|
|
||||||
|
_.merge(result, comparison._doc)
|
||||||
|
return res.json(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new comparison
|
||||||
|
exports.create = function(req, res) {
|
||||||
|
//we do not allow the api client to change the id willy-nilly!
|
||||||
|
if (req.body._id) { delete req.body._id; }
|
||||||
|
|
||||||
|
var comparison = req.body;
|
||||||
|
|
||||||
|
|
||||||
|
//and add to the db
|
||||||
|
Comparison.create(comparison, function(err, comparison) {
|
||||||
|
if(err) { return handleError(res, err); }
|
||||||
|
|
||||||
|
//save the document and return
|
||||||
|
comparison.save(function (err, comparison) {
|
||||||
|
if(err) { return handleError(res, err); }
|
||||||
|
return res.json(201, comparison);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleError(res, err) {
|
||||||
|
return res.send(500, err);
|
||||||
|
}
|
13
server/api/comparison/comparison.model.js
Normal file
13
server/api/comparison/comparison.model.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var mongoose = require('mongoose'),
|
||||||
|
Schema = mongoose.Schema;
|
||||||
|
|
||||||
|
var ComparisonSchema = new Schema({
|
||||||
|
created: {type: Date, default: Date.now},
|
||||||
|
|
||||||
|
a: String,
|
||||||
|
b: String,
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = mongoose.model('Comparison', ComparisonSchema);
|
16
server/api/comparison/index.js
Normal file
16
server/api/comparison/index.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var express = require('express');
|
||||||
|
var controller = require('./comparison.controller');
|
||||||
|
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
//router.get('/', controller.index);
|
||||||
|
|
||||||
|
router.get('/:id', controller.showComparison);
|
||||||
|
router.get('/wdiff/:id', controller.wdiffMarkdownComparison);
|
||||||
|
|
||||||
|
router.post('/', controller.create);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -9,6 +9,8 @@ var errors = require('./components/errors');
|
|||||||
module.exports = function(app) {
|
module.exports = function(app) {
|
||||||
|
|
||||||
// Insert routes below
|
// Insert routes below
|
||||||
|
|
||||||
|
app.use('/api/compare', require('./api/comparison'));
|
||||||
app.use('/api/documents', require('./api/document'));
|
app.use('/api/documents', require('./api/document'));
|
||||||
app.use('/api/wdiff', require('./api/wdiff'));
|
app.use('/api/wdiff', require('./api/wdiff'));
|
||||||
app.use('/api/users', require('./api/user'));
|
app.use('/api/users', require('./api/user'));
|
||||||
|
Loading…
Reference in New Issue
Block a user