challenges: switch from ngRoute to ui-router

This commit is contained in:
Tyler Renelle
2013-10-27 22:27:07 -07:00
parent f178eb2322
commit 35c4a62de0
23 changed files with 614 additions and 708 deletions

View File

@@ -19,7 +19,7 @@
"angular-resource": "1.2.0-rc.2", "angular-resource": "1.2.0-rc.2",
"angular-ui": "~0.4.0", "angular-ui": "~0.4.0",
"angular-bootstrap": "~0.5.0", "angular-bootstrap": "~0.5.0",
"habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared.git#rewrite", "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared.git#challenges",
"bootstrap-tour": "0.5.0", "bootstrap-tour": "0.5.0",
"BrowserQuest": "https://github.com/mozilla/BrowserQuest.git", "BrowserQuest": "https://github.com/mozilla/BrowserQuest.git",
"github-buttons": "git://github.com/mdo/github-buttons.git", "github-buttons": "git://github.com/mdo/github-buttons.git",
@@ -29,11 +29,11 @@
"sticky": "*", "sticky": "*",
"bootstrap-datepicker": "~1.2.0", "bootstrap-datepicker": "~1.2.0",
"bootstrap": "v2.3.2", "bootstrap": "v2.3.2",
"angular-route": "1.2.0-rc.2",
"angular-ui-utils": "~0.0.4", "angular-ui-utils": "~0.0.4",
"angular-sanitize": "1.2.0-rc.2", "angular-sanitize": "1.2.0-rc.2",
"marked": "~0.2.9", "marked": "~0.2.9",
"JavaScriptButtons": "git://github.com/paypal/JavaScriptButtons.git#master" "JavaScriptButtons": "git://github.com/paypal/JavaScriptButtons.git#master",
"angular-ui-router": "eda67d2da08cbe2aa1aa39ef154a87c7afe480ec"
}, },
"resolutions": { "resolutions": {
"jquery": "~2.0.3", "jquery": "~2.0.3",

View File

@@ -1,21 +1,123 @@
"use strict"; "use strict";
window.habitrpg = angular.module('habitrpg', window.habitrpg = angular.module('habitrpg',
['ngRoute', 'ngResource', 'ngSanitize', 'userServices', 'groupServices', 'memberServices', 'challengeServices', 'sharedServices', 'authServices', 'notificationServices', 'guideServices', 'ui.bootstrap', 'ui.keypress']) ['ngRoute', 'ngResource', 'ngSanitize', 'userServices', 'groupServices', 'memberServices', 'challengeServices', 'sharedServices', 'authServices', 'notificationServices', 'guideServices', 'ui.bootstrap', 'ui.keypress', 'ui.router'])
.constant("API_URL", "") .constant("API_URL", "")
.constant("STORAGE_USER_ID", 'habitrpg-user') .constant("STORAGE_USER_ID", 'habitrpg-user')
.constant("STORAGE_SETTINGS_ID", 'habit-mobile-settings') .constant("STORAGE_SETTINGS_ID", 'habit-mobile-settings')
//.constant("STORAGE_GROUPS_ID", "") // if we decide to take groups offline //.constant("STORAGE_GROUPS_ID", "") // if we decide to take groups offline
.config(['$routeProvider', '$httpProvider', 'STORAGE_SETTINGS_ID', .config(['$stateProvider', '$urlRouterProvider', '$httpProvider', 'STORAGE_SETTINGS_ID',
function($routeProvider, $httpProvider, STORAGE_SETTINGS_ID) { function($stateProvider, $urlRouterProvider, $httpProvider, STORAGE_SETTINGS_ID) {
$routeProvider
//.when('/login', {templateUrl: 'views/login.html'})
.when('/tasks', {templateUrl: 'templates/habitrpg-main.html'})
.when('/options', {templateUrl: 'templates/habitrpg-options.html'})
.otherwise({redirectTo: '/tasks'}); $urlRouterProvider
// Setup default selected tabs
.when('/options', '/options/profile/avatar')
.when('/options/profile', '/options/profile/avatar')
.when('/options/groups', '/options/groups/tavern')
.when('/options/inventory', '/options/inventory/inventory')
// redirect states that don't match
.otherwise("/tasks");
$stateProvider
// Tasks
.state('tasks', {
url: "/tasks",
templateUrl: "partials/main.html"
})
// Options
.state('options', {
url: "/options",
templateUrl: "partials/options.html",
controller: function(){}
})
// Options > Profile
.state('options.profile', {
url: "/profile",
templateUrl: "partials/options.profile.html",
controller: 'UserCtrl'
})
.state('options.profile.avatar', {
url: "/avatar",
templateUrl: "partials/options.profile.avatar.html"
})
.state('options.profile.stats', {
url: "/stats",
templateUrl: "partials/options.profile.stats.html"
})
.state('options.profile.profile', {
url: "/stats",
templateUrl: "partials/options.profile.profile.html"
})
// Options > Groups
.state('options.groups', {
url: "/groups",
templateUrl: "partials/options.groups.html"
})
.state('options.groups.tavern', {
url: "/tavern",
templateUrl: "partials/options.groups.tavern.html",
controller: 'TavernCtrl'
// TODO this doesn't work, seems ngResource doesn't get the .then() function
// resolve: {
// group: ['Groups', function(Groups){
// //return Groups.fetchTavern();
// }]
// }
})
.state('options.groups.party', {
url: '/party',
templateUrl: "partials/options.groups.party.html",
controller: 'PartyCtrl'
})
.state('options.groups.guilds', {
url: '/party',
templateUrl: "partials/options.groups.guilds.html",
controller: 'GuildsCtrl'
})
// Options > Inventory
.state('options.inventory', {
url: '/inventory',
templateUrl: "partials/options.inventory.html"
})
.state('options.inventory.inventory', {
url: '/inventory',
templateUrl: "partials/options.inventory.inventory.html"
})
.state('options.inventory.stable', {
url: '/stable',
templateUrl: "partials/options.inventory.stable.html"
})
// Options > Challenges
.state('options.challenges', {
url: "/challenges",
controller: 'ChallengesCtrl',
templateUrl: "partials/options.challenges.html",
resolve: {
groups: ['$http', 'API_URL', function($http, API_URL){
// TODO come up with more unified ngResource-style approach
return $http.get(API_URL + '/api/v1/groups?minimal=true');
}],
challenges: ['Challenges', function(Challenges){
return Challenges.Challenge.query();
}]
}
})
// Options > Settings
.state('options.settings', {
url: "/settings",
controller: 'SettingsCtrl',
templateUrl: "partials/options.settings.html"
})
var settings = JSON.parse(localStorage.getItem(STORAGE_SETTINGS_ID)); var settings = JSON.parse(localStorage.getItem(STORAGE_SETTINGS_ID));
if (settings && settings.auth) { if (settings && settings.auth) {

View File

@@ -1,13 +1,11 @@
"use strict"; "use strict";
habitrpg.controller("ChallengesCtrl", ['$scope', '$rootScope', 'User', 'Challenges', 'Notification', '$http', 'API_URL', '$compile', habitrpg.controller("ChallengesCtrl", ['$scope', 'User', 'Challenges', 'Notification', '$compile', 'groups', 'challenges',
function($scope, $rootScope, User, Challenges, Notification, $http, API_URL, $compile) { function($scope, User, Challenges, Notification, $compile, groups, challenges) {
$http.get(API_URL + '/api/v1/groups?minimal=true').success(function(groups){ // groups & challenges are loaded as `resolve` via ui-router (see app.js)
$scope.groups = groups; $scope.groups = groups;
}); $scope.challenges = challenges;
$scope.challenges = Challenges.Challenge.query();
//------------------------------------------------------------ //------------------------------------------------------------
// Challenge // Challenge
@@ -92,34 +90,6 @@ habitrpg.controller("ChallengesCtrl", ['$scope', '$rootScope', 'User', 'Challeng
// TODO persist // TODO persist
} }
/**
* Render graphs for user scores when the "Challenges" tab is clicked
*/
//TODO
// 1. on main tab click or party
// * sort & render graphs for party
// 2. guild -> all guilds
// 3. public -> all public
// $('#profile-challenges-tab-link').on 'shown', ->
// async.each _.toArray(model.get('groups')), (g) ->
// async.each _.toArray(g.challenges), (chal) ->
// async.each _.toArray(chal.tasks), (task) ->
// async.each _.toArray(chal.members), (member) ->
// if (history = member?["#{task.type}s"]?[task.id]?.history) and !!history
// data = google.visualization.arrayToDataTable _.map(history, (h)-> [h.date,h.value])
// options =
// backgroundColor: { fill:'transparent' }
// width: 150
// height: 50
// chartArea: width: '80%', height: '80%'
// axisTitlePosition: 'none'
// legend: position: 'bottom'
// hAxis: gridlines: color: 'transparent' # since you can't seem to *remove* gridlines...
// vAxis: gridlines: color: 'transparent'
// chart = new google.visualization.LineChart $(".challenge-#{chal.id}-member-#{member.id}-history-#{task.id}")[0]
// chart.draw(data, options)
/* /*
-------------------------- --------------------------
Unsubscribe functions Unsubscribe functions

View File

@@ -1,7 +1,7 @@
"use strict"; "use strict";
habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'API_URL', '$q', 'User', 'Members', '$location', habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'API_URL', '$q', 'User', 'Members', '$location', '$state',
function($scope, $rootScope, Groups, $http, API_URL, $q, User, Members, $location) { function($scope, $rootScope, Groups, $http, API_URL, $q, User, Members, $location, $state) {
$scope.isMember = function(user, group){ $scope.isMember = function(user, group){
return ~(group.members.indexOf(user._id)); return ~(group.members.indexOf(user._id));
@@ -25,10 +25,10 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
$scope.clickMember = function(uid, forceShow) { $scope.clickMember = function(uid, forceShow) {
if (User.user._id == uid && !forceShow) { if (User.user._id == uid && !forceShow) {
if ($location.path() == '/tasks') { if ($state.is('tasks')) {
$location.path('/options'); $state.go('options');
} else { } else {
$location.path('/tasks'); $state.go('tasks');
} }
} else { } else {
// We need the member information up top here, but then we pass it down to the modal controller // We need the member information up top here, but then we pass it down to the modal controller
@@ -117,6 +117,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
.controller("GuildsCtrl", ['$scope', 'Groups', 'User', '$rootScope', .controller("GuildsCtrl", ['$scope', 'Groups', 'User', '$rootScope',
function($scope, Groups, User, $rootScope) { function($scope, Groups, User, $rootScope) {
Groups.fetchGuilds();
$scope.type = 'guild'; $scope.type = 'guild';
$scope.text = 'Guild'; $scope.text = 'Guild';
$scope.newGroup = new Groups.Group({type:'guild', privacy:'private', leader: User.user._id, members: [User.user._id]}); $scope.newGroup = new Groups.Group({type:'guild', privacy:'private', leader: User.user._id, members: [User.user._id]});
@@ -202,6 +203,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
.controller("TavernCtrl", ['$scope', 'Groups', 'User', .controller("TavernCtrl", ['$scope', 'Groups', 'User',
function($scope, Groups, User) { function($scope, Groups, User) {
Groups.fetchTavern();
$scope.group = Groups.groups.tavern; $scope.group = Groups.groups.tavern;
$scope.rest = function(){ $scope.rest = function(){

View File

@@ -3,8 +3,8 @@
/* Make user and settings available for everyone through root scope. /* Make user and settings available for everyone through root scope.
*/ */
habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams',
function($scope, $rootScope, $location, User, $http) { function($scope, $rootScope, $location, User, $http, $state, $stateParams) {
$rootScope.modals = {}; $rootScope.modals = {};
$rootScope.modals.achievements = {}; $rootScope.modals.achievements = {};
$rootScope.User = User; $rootScope.User = User;
@@ -12,6 +12,10 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
$rootScope.settings = User.settings; $rootScope.settings = User.settings;
$rootScope.flash = {errors: [], warnings: []}; $rootScope.flash = {errors: [], warnings: []};
// Angular UI Router
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
// indexOf helper // indexOf helper
$scope.indexOf = function(haystack, needle){ $scope.indexOf = function(haystack, needle){
return ~haystack.indexOf(needle); return ~haystack.indexOf(needle);

View File

@@ -44,9 +44,9 @@ angular.module('groupServices', ['ngResource']).
fetchGuilds: _.once(function(){ fetchGuilds: _.once(function(){
$('#loading-indicator').show(); $('#loading-indicator').show();
Group.query({type:'guilds'}, function(_groups){ Group.query({type:'guilds'}, function(_groups){
$('#loading-indicator').hide();
guildsQ.resolve(_groups); guildsQ.resolve(_groups);
Members.populate(_groups); Members.populate(_groups);
$('#loading-indicator').hide();
}) })
Group.query({type:'public'}, function(_groups){ Group.query({type:'public'}, function(_groups){
publicQ.resolve(_groups); publicQ.resolve(_groups);
@@ -58,8 +58,8 @@ angular.module('groupServices', ['ngResource']).
$('#loading-indicator').show(); $('#loading-indicator').show();
Group.query({type:'tavern'}, function(_groups){ Group.query({type:'tavern'}, function(_groups){
$('#loading-indicator').hide(); $('#loading-indicator').hide();
tavernQ.resolve(_groups[0]);
Members.populate(_groups[0]); Members.populate(_groups[0]);
tavernQ.resolve(_groups[0]);
}) })
}), }),

View File

@@ -20,6 +20,8 @@ var ChallengeSchema = new Schema({
//}, //},
timestamp: {type: Date, 'default': Date.now}, timestamp: {type: Date, 'default': Date.now},
members: [{type: String, ref: 'User'}] members: [{type: String, ref: 'User'}]
}, {
minimize: 'false'
}); });
ChallengeSchema.virtual('tasks').get(function () { ChallengeSchema.virtual('tasks').get(function () {

View File

@@ -7,37 +7,14 @@ var GroupSchema = new Schema({
_id: {type: String, 'default': helpers.uuid}, _id: {type: String, 'default': helpers.uuid},
name: String, name: String,
description: String, description: String,
leader: { leader: {type: String, ref: 'User'},
type: String, members: [{type: String, ref: 'User'}],
ref: 'User' invites: [{type: String, ref: 'User'}],
}, type: {type: String, "enum": ['guild', 'party']},
members: [ privacy: {type: String, "enum": ['private', 'public']},
{ _v: {Number: Number,'default': 0},
type: String,
ref: 'User'
}
],
invites: [
{
type: String,
ref: 'User'
}
],
type: {
type: String,
"enum": ['guild', 'party']
},
privacy: {
type: String,
"enum": ['private', 'public']
},
_v: {
Number: Number,
'default': 0
},
websites: Array, websites: Array,
chat: Array, chat: Array,
/* /*
# [{ # [{
# timestamp: Date # timestamp: Date

View File

@@ -31,6 +31,8 @@ var TaskSchema = new Schema({
broken: String // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, etc broken: String // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, etc
// group: {type: 'Strign', ref: 'Group'} // if we restore this, rename `id` above to `challenge` // group: {type: 'Strign', ref: 'Group'} // if we restore this, rename `id` above to `challenge`
} }
}, {
minimize: 'false'
}); });
TaskSchema.methods.toJSON = function() { TaskSchema.methods.toJSON = function() {

View File

@@ -31,6 +31,7 @@ html
script(type='text/javascript', src='/bower_components/bootstrap-growl/jquery.bootstrap-growl.min.js') script(type='text/javascript', src='/bower_components/bootstrap-growl/jquery.bootstrap-growl.min.js')
script(type='text/javascript', src='/bower_components/bootstrap-tour/build/js/bootstrap-tour.min.js') script(type='text/javascript', src='/bower_components/bootstrap-tour/build/js/bootstrap-tour.min.js')
script(type='text/javascript', src='/bower_components/angular/angular.js') script(type='text/javascript', src='/bower_components/angular/angular.js')
script(type='text/javascript', src='/bower_components/angular-ui-router/release/angular-ui-router.js')
script(type='text/javascript', src='/bower_components/angular-sanitize/angular-sanitize.min.js') script(type='text/javascript', src='/bower_components/angular-sanitize/angular-sanitize.min.js')
script(type='text/javascript', src='/bower_components/marked/lib/marked.js') script(type='text/javascript', src='/bower_components/marked/lib/marked.js')
@@ -109,7 +110,7 @@ html
.exp-chart(ng-show='charts.exp') .exp-chart(ng-show='charts.exp')
#main(ng-view) #main(ui-view)
include ./shared/footer include ./shared/footer

View File

@@ -1,4 +1,4 @@
script(id='templates/habitrpg-main.html', type="text/ng-template") script(id='partials/main.html', type="text/ng-template")
include ./filters include ./filters
div(ng-controller='TasksCtrl') div(ng-controller='TasksCtrl')
habitrpg-tasks(main='true', obj='user') habitrpg-tasks(main='true', obj='user')

View File

@@ -1,176 +0,0 @@
<main>
<app:widgets:tabs>
<!--<@headers>-->
<app:widgets:tab-header group="challenges" tab="party" title="Party" default="true" />
<app:widgets:tab-header group="challenges" tab="guild" title="Guild" />
<app:widgets:tab-header group="challenges" tab="public" title="Public" />
<!--</@headers>-->
<app:widgets:tab-content group="challenges" tab="party" default="true">
{{#unless _page.party.id}}
Join a party first.
{{else}}
<app:challenges:list type="party" gid="{{_page.party.id}}" text="Party" list="{_page.lists.challenges[_page.party.id]}" />
{{/}}
</app:widgets:tab-content>
<app:widgets:tab-content group="challenges" tab="guild">
<ul class="nav nav-pills">
{{#each _page.guilds as :guild}}
<li class="{{#if equal($index,0)}}active{{/}}"><a data-toggle='tab' data-target="#challenges-guild-{:guild.id}">{{:guild.name}}</a></li>
{{/}}
</ul>
<div class="tab-content">
{{#each _page.guilds as :guild}}
<div class="tab-pane {{#if equal($index,0)}}active{{/}}" id="challenges-guild-{{:guild.id}}">
<app:challenges:list type="guild" gid="{{:guild.id}}" text="Guild" list="{_page.lists.challenges[:guild.id]}" />
</div>
{{/}}
</div>
</app:widgets:tab-content>
<app:widgets:tab-content group="challenges" tab="public">
<app:challenges:list type="public" gid="habitrpg" text="Public" list="{_page.lists.challenges.habitrpg}" />
</app:widgets:tab-content>
</app:widgets:tabs>
</main>
<list>
<div class="{#unless _page.new.challenge}hidden{/}">
<app:challenges:create-form />
</div>
<div class="{#if _page.new.challenge}hidden{/}">
<app:challenges:create-button type='{{@type}}' gid={{@gid}} text={{@text}} />
{#each @list as :challenge}
<app:challenges:list-entry challenge={:challenge} />
{/}
<hr/>
</div>
</list>
<list-entry>
<div class="accordion-group">
<div class="accordion-heading">
<ul class='pull-right challenge-accordion-header-specs'>
<li>
{count(@challenge.members)} Subscribers
</li>
<li>
<!-- prize -->
{#if @challenge.prize}
<table><tr><td>{@challenge.prize}</td><td><span class="Pet_Currency_Gem1x"></span></td><td> Prize</td></tr></table>
{/}
</li>
<li>
<!-- subscribe / unsubscribe -->
{#with @challenge}
<a x-bind="click:challenges.challengeUnsubscribe" class='btn btn-small btn-danger {#unless indexOf(_page.user.pub.challenges,@challenge.id)}hidden{/}'><i class='icon-ban-circle'></i> Unsubscribe</a>
<a x-bind="click:challenges.subscribe" class='btn btn-small btn-success {#if indexOf(_page.user.pub.challenges,@challenge.id)}hidden{/}'><i class='icon-ok'></i> Subscribe</a>
{/}
</li>
</ul>
<a class="accordion-toggle" data-toggle="collapse" href="#accordion-challenge-{{@challenge.id}}">{@challenge.name} (by {@challenge.user.name})</a>
</div>
<div id="accordion-challenge-{{@challenge.id}}" class="accordion-body collapse">
<div class="accordion-inner">
<!-- Edit button -->
<span style='position:absolute; right:0;'>
{#if and(not(_page.editing.challenges[@challenge.id]),equal(@challenge.user.uid,_session.userId))}
<ul class='nav nav-pills'><li>
<a x-bind='click:challenges.toggleEdit' data-id={{@challenge.id}} ><i class=icon-pencil></i></a>
</li></ul>
{else}
<ul class='nav nav-pills'><li>
<a x-bind='click:challenges.toggleEdit' data-id={{@challenge.id}} ><i class=icon-ok></i></a>
</li></ul>
{/}
</span>
{#if _page.editing.challenges[@challenge.id]}
<div class='-options'>
<input type=text class='option-content' value={@challenge.name} />
<textarea cols=3 class='option-content' placeholder='Description'>{@challenge.description}</textarea>
<!--<input type=number class='option-content' placeholder='Gems Prize' value={@challenge.prize} />-->
</div>
{{#with @challenge}}
<a class='btn btn-small btn-danger' x-bind=click:challenges.delete >Delete</a>
{{/}}
{/}
{#if @challenge.description}<div>{@challenge.description}</div>{/}
<div class="grid">
<app:tasks:task-lists
editable={_page.editing.challenges[@challenge.id]}
habits={@challenge.habits}
dailys={@challenge.dailys}
todos={@challenge.todos}
rewards={@challenge.rewards}
/>
</div>
<h3>Statistics</h3>
{#each @challenge.members as :member}
<h4>{:member.name}</h4>
<div class="grid">
<div class="module">
<app:challenges:stats header=Habits challenge={@challenge} member={:member} list={@challenge.habits} />
</div>
<div class="module">
<app:challenges:stats header=Dailies challenge={@challenge} member={:member} list={@challenge.dailys} />
</div>
<div class="module">
<app:challenges:stats header=Todos challenge={@challenge} member={:member} list={@challenge.todos} />
</div>
</div>
{/}
</div>
</div>
</div>
</list-entry>
<stats>
<h5>{@header}</h5>
<div>
{#each @list as :task}
<table><tr>
<td>
<!-- FIXME commented section below isn't getting updated dynamically, temp solution is less efficient -->
<strong>{:task.text}</strong>: {challengeMemberScore(@member,:task)} <!--{round(@member[@taskType]s[:task.id].value)}-->
</td>
<td>
<div style='margin-left: 10px' class="challenge-{{@challenge.id}}-member-{{@member.id}}-history-{{:task.id}}"></div>
</td>
</tr></table>
{/}
</div>
</stats>
<create-button>
<a x-bind='click:challenges.create' class='btn btn-success' data-type={{@type}} data-gid={{@gid}} >Create {{@text}} Challenge</a>
</create-button>
<create-form>
<form x-bind="submit:challenges.save">
<div>
<input type='submit' class='btn btn-success' value='Save' />
<input type='button' x-bind='click:challenges.discard' class='btn btn-danger' value=Discard />
</div>
<div class='challenge-options'>
<input type='text' class='option-content' value={_page.new.challenge.name} placeholder="Challenge Title" required />
</div>
</form>
<div class="grid">
<app:tasks:task-lists
habits={_page.new.challenge.habits}
dailys={_page.new.challenge.dailys}
todos={_page.new.challenge.todos}
rewards={_page.new.challenge.rewards}
editable=true />
</div>
</create-form>

View File

@@ -1,4 +1,5 @@
.row-fluid(ng-controller='ChallengesCtrl') script(type='text/ng-template', id='partials/options.challenges.html')
.row-fluid
.span2.well .span2.well
h4 Filters h4 Filters
ul ul

View File

@@ -1,14 +1,10 @@
// FIXME note, due to https://github.com/angular-ui/bootstrap/issues/783 we can't use nested angular-bootstrap tabs // FIXME note, due to https://github.com/angular-ui/bootstrap/issues/783 we can't use nested angular-bootstrap tabs
// Subscribe to that ticket & change this when they fix // Subscribe to that ticket & change this when they fix
ul.nav.nav-tabs script(type='text/ng-template', id='partials/options.groups.tavern.html')
li.active include ./tavern
a(data-target='#groups-party', data-toggle='tab') Party
li
a(data-target='#groups-guilds', data-toggle='tab', ng-click='fetchGuilds()') Guilds
.tab-content(ng-controller='PartyCtrl') script(type='text/ng-template', id='partials/options.groups.party.html')
#groups-party.tab-pane.active
div(ng-show='group._id') div(ng-show='group._id')
include ./group include ./group
div(ng-hide='group._id') div(ng-hide='group._id')
@@ -27,7 +23,7 @@ ul.nav.nav-tabs
{{user.id}} {{user.id}}
include ./create-group include ./create-group
#groups-guilds.tab-pane(ng-controller='GuildsCtrl') script(type='text/ng-template', id='partials/options.groups.guilds.html')
ul.nav.nav-tabs ul.nav.nav-tabs
li.active li.active
a(data-target='#groups-public-guilds', data-toggle='tab') Public Guilds a(data-target='#groups-public-guilds', data-toggle='tab') Public Guilds
@@ -64,3 +60,20 @@ ul.nav.nav-tabs
.tab-pane#groups-create-guild .tab-pane#groups-create-guild
include ./create-group include ./create-group
script(type='text/ng-template', id='partials/options.groups.html')
ul.nav.nav-tabs
li(ng-class="{ active: $state.includes('options.groups.tavern') }")
a(ui-sref='options.groups.tavern')
i.icon-eye-close
| Tavern
li(ng-class="{ active: $state.includes('options.groups.party') }")
a(ui-sref='options.groups.party')
| Party
li(ng-class="{ active: $state.includes('options.groups.guilds') }")
a(ui-sref='options.groups.guilds')
| Guilds
.tab-content
.tab-pane.active
div(ui-view)

View File

@@ -1,4 +1,4 @@
.row-fluid(ng-controller='TavernCtrl') .row-fluid
.span4 .span4
.tavern-pane .tavern-pane
table table

View File

@@ -1,64 +1,37 @@
script(id='templates/habitrpg-options.html', type="text/ng-template") include ./profile
include ./groups/index
include ./challenges
include ./inventory/index
include ./settings
script(id='partials/options.html', type="text/ng-template")
.grid .grid
.module.full-width .module.full-width
span.option-box.pull-right.wallet span.option-box.pull-right.wallet
include ../shared/gems include ../shared/gems
ul.nav.nav-tabs ul.nav.nav-tabs
li.active li(ng-class="{ active: $state.includes('options.profile') }")
a(data-toggle='tab', data-target='#profile-tab') a(ui-sref='options.profile')
i.icon-user i.icon-user
| Profile | Profile
li li(ng-class="{ active: $state.includes('options.groups') }")
a(data-toggle='tab',data-target='#groups-tab', ng-click='fetchParty()') a(ui-sref='options.groups')
i.icon-heart i.icon-heart
| Groups | Groups
li(ng-show='user.flags.dropsEnabled') li(ng-class="{ active: $state.includes('options.inventory') }", ng-if='user.flags.dropsEnabled')
a(data-toggle='tab',data-target='#inventory-tab') a(ui-sref='options.inventory')
i.icon-gift i.icon-gift
| Inventory | Inventory
li(ng-show='user.flags.dropsEnabled') li(ng-class="{ active: $state.includes('options.challenges') }")
a(data-toggle='tab',data-target='#stable-tab') a(ui-sref='options.challenges')
i.icon-leaf
| Stable
li
a(data-toggle='tab',data-target='#tavern-tab', ng-click='fetchTavern()')
i.icon-eye-close
| Tavern
li
a(data-toggle='tab',data-target='#achievements-tab')
i.icon-certificate
| Achievements
li
a(data-toggle='tab',data-target='#challenges-tab')
i.icon-bullhorn i.icon-bullhorn
| Challenges | Challenges
li li(ng-class="{ active: $state.includes('options.settings') }")
a(data-toggle='tab',data-target='#settings-tab') a(ui-sref='options.settings')
i.icon-wrench i.icon-wrench
| Settings | Settings
.tab-content .tab-content
.tab-pane.active#profile-tab .tab-pane.active
include ./profile div(ui-view)
.tab-pane#groups-tab
include ./groups/index
.tab-pane#inventory-tab
include ./inventory
.tab-pane#stable-tab
include ./pets
.tab-pane#tavern-tab
include ./groups/tavern
.tab-pane#achievements-tab(ng-controller='UserCtrl')
include ../shared/profiles/achievements
.tab-pane#challenges-tab
include ./challenges
.tab-pane#settings-tab
include ./settings

View File

@@ -1,54 +0,0 @@
.row-fluid(ng-controller='InventoryCtrl')
.span6.border-right
h2 Inventory
p.well Combine eggs with hatching potions to make pets by clicking an egg and then a potion. Sell unwanted drops to Alexander the Merchant.
menu.inventory-list(type='list')
li.customize-menu
menu.pets-menu(label='Eggs ({{userEggs.length}})')
p(ng-show='userEggs.length < 1') You don't have any eggs yet.
div(ng-repeat='egg in userEggs track by $index')
button.customize-option(tooltip='{{egg.text}}', ng-click='chooseEgg(egg, $index)', class='Pet_Egg_{{egg.name}}', ng-class='selectableInventory(egg, selectedPotion.name, $index)')
p {{egg.text}}
li.customize-menu
menu.hatchingPotion-menu(label='Hatching Potions ({{userHatchingPotions.length}})')
p(ng-show='userHatchingPotions.length < 1') You don't have any hatching potions yet.
div(ng-repeat='hatchingPotion in userHatchingPotions track by $index')
button.customize-option(tooltip='{{hatchingPotion}}', ng-click='choosePotion(hatchingPotion, $index)', class='Pet_HatchingPotion_{{hatchingPotion}}', ng-class='selectableInventory(selectedEgg, hatchingPotion, $index)')
p {{hatchingPotion}}
.span6
h2 Market
.row-fluid(ng-controller='MarketCtrl')
table.NPC-Alex-container
tr
td
.NPC-Alex.pull-left
td
.popover.static-popover.fade.right.in
.arrow
h3.popover-title
a(target='_blank', href='http://www.kickstarter.com/profile/523661924') Alexander the Merchant
.popover-content
p
| Welcome to the Market. Dying to get that particular pet you're after, but don't want to wait for it to drop? Buy it here! If you have unwanted drops, sell them to me.
p
button.btn.btn-primary(ng-show='selectedEgg', ng-click='sellInventory()')
| Sell {{selectedEgg.name}} for {{selectedEgg.value}} GP
button.btn.btn-primary(ng-show='selectedPotion', ng-click='sellInventory()')
| Sell {{selectedPotion.name}} for {{selectedPotion.value}} GP
menu.inventory-list(type='list')
li.customize-menu
menu.pets-menu(label='Eggs')
div(ng-repeat='egg in eggs track by $index')
button.customize-option(tooltip='{{egg.text}} - {{egg.value}} Gem(s)', ng-click='buy("egg", egg)', class='Pet_Egg_{{egg.name}}')
p {{egg.text}}
li.customize-menu
menu.pets-menu(label='Hatching Potions')
div(ng-repeat='hatchingPotion in hatchingPotions track by $index')
button.customize-option(tooltip='{{hatchingPotion.text}} - {{hatchingPotion.value}} Gem(s)', ng-click='buy("hatchingPotion", hatchingPotion)', class='Pet_HatchingPotion_{{hatchingPotion.name}}')
p {{hatchingPotion.text}}

View File

@@ -0,0 +1,15 @@
include ./inventory
include ./stable
script(type='text/ng-template', id='partials/options.inventory.html')
ul.nav.nav-tabs
li(ng-class="{ active: $state.includes('options.inventory.inventory') }")
a(ui-sref='options.inventory.inventory')
| Inventory
li(ng-class="{ active: $state.includes('options.inventory.stable') }")
a(ui-sref='options.inventory.stable')
| Stable
.tab-content
.tab-pane.active
div(ui-view)

View File

@@ -0,0 +1,55 @@
script(type='text/ng-template', id='partials/options.inventory.inventory.html')
.row-fluid(ng-controller='InventoryCtrl')
.span6.border-right
h2 Inventory
p.well Combine eggs with hatching potions to make pets by clicking an egg and then a potion. Sell unwanted drops to Alexander the Merchant.
menu.inventory-list(type='list')
li.customize-menu
menu.pets-menu(label='Eggs ({{userEggs.length}})')
p(ng-show='userEggs.length < 1') You don't have any eggs yet.
div(ng-repeat='egg in userEggs track by $index')
button.customize-option(tooltip='{{egg.text}}', ng-click='chooseEgg(egg, $index)', class='Pet_Egg_{{egg.name}}', ng-class='selectableInventory(egg, selectedPotion.name, $index)')
p {{egg.text}}
li.customize-menu
menu.hatchingPotion-menu(label='Hatching Potions ({{userHatchingPotions.length}})')
p(ng-show='userHatchingPotions.length < 1') You don't have any hatching potions yet.
div(ng-repeat='hatchingPotion in userHatchingPotions track by $index')
button.customize-option(tooltip='{{hatchingPotion}}', ng-click='choosePotion(hatchingPotion, $index)', class='Pet_HatchingPotion_{{hatchingPotion}}', ng-class='selectableInventory(selectedEgg, hatchingPotion, $index)')
p {{hatchingPotion}}
.span6
h2 Market
.row-fluid(ng-controller='MarketCtrl')
table.NPC-Alex-container
tr
td
.NPC-Alex.pull-left
td
.popover.static-popover.fade.right.in
.arrow
h3.popover-title
a(target='_blank', href='http://www.kickstarter.com/profile/523661924') Alexander the Merchant
.popover-content
p
| Welcome to the Market. Dying to get that particular pet you're after, but don't want to wait for it to drop? Buy it here! If you have unwanted drops, sell them to me.
p
button.btn.btn-primary(ng-show='selectedEgg', ng-click='sellInventory()')
| Sell {{selectedEgg.name}} for {{selectedEgg.value}} GP
button.btn.btn-primary(ng-show='selectedPotion', ng-click='sellInventory()')
| Sell {{selectedPotion.name}} for {{selectedPotion.value}} GP
menu.inventory-list(type='list')
li.customize-menu
menu.pets-menu(label='Eggs')
div(ng-repeat='egg in eggs track by $index')
button.customize-option(tooltip='{{egg.text}} - {{egg.value}} Gem(s)', ng-click='buy("egg", egg)', class='Pet_Egg_{{egg.name}}')
p {{egg.text}}
li.customize-menu
menu.pets-menu(label='Hatching Potions')
div(ng-repeat='hatchingPotion in hatchingPotions track by $index')
button.customize-option(tooltip='{{hatchingPotion.text}} - {{hatchingPotion.value}} Gem(s)', ng-click='buy("hatchingPotion", hatchingPotion)', class='Pet_HatchingPotion_{{hatchingPotion.name}}')
p {{hatchingPotion.text}}

View File

@@ -0,0 +1,30 @@
script(type='text/ng-template', id='partials/options.inventory.stable.html')
.stable(ng-controller='PetsCtrl')
.NPC-Matt
.popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;')
.arrow
h3.popover-title
a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch
.popover-content
p
| Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to adventure at your side - they aren't much help yet, but I forsee a time when they're able to
a(href='https://trello.com/card/mounts/50e5d3684fe3a7266b0036d6/221') grow into powerful steeds
| ! Until that day,
a(target='_blank', href='https://f.cloud.github.com/assets/2374703/164631/3ed5fa6c-78cd-11e2-8743-f65ac477b55e.png') have a look-see
| at all the pets you can collect.
h4 {{userPets.length}} / {{totalPets}} Pets Found
menu.pets(type='list')
li.customize-menu(ng-repeat='pet in pets')
menu
div(ng-repeat='potion in hatchingPotions', tooltip='{{potion.name}} {{pet.name}}')
button(class="pet-button Pet-{{pet.name}}-{{potion.name}}", ng-show='hasPet(pet.name, potion.name)', ng-class="{active: isCurrentPet(pet.name, potion.name)}", ng-click='choosePet(pet.name, potion.name)')
button(class="pet-button pet-not-owned", ng-hide='hasPet(pet.name, potion.name)')
img(src='/bower_components/habitrpg-shared/img/PixelPaw.png')
h4 Rare Pets
menu
div(ng-if='hasPet("Wolf", "Veteran")')
button(class="pet-button Pet-Wolf-Veteran", ng-class='{active: isCurrentPet("Wolf", "Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf')
div(ng-if='hasPet("Wolf", "Cerberus")')
button(class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup')

View File

@@ -1,29 +0,0 @@
.stable(ng-controller='PetsCtrl')
.NPC-Matt
.popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;')
.arrow
h3.popover-title
a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch
.popover-content
p
| Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to adventure at your side - they aren't much help yet, but I forsee a time when they're able to
a(href='https://trello.com/card/mounts/50e5d3684fe3a7266b0036d6/221') grow into powerful steeds
| ! Until that day,
a(target='_blank', href='https://f.cloud.github.com/assets/2374703/164631/3ed5fa6c-78cd-11e2-8743-f65ac477b55e.png') have a look-see
| at all the pets you can collect.
h4 {{userPets.length}} / {{totalPets}} Pets Found
menu.pets(type='list')
li.customize-menu(ng-repeat='pet in pets')
menu
div(ng-repeat='potion in hatchingPotions', tooltip='{{potion.name}} {{pet.name}}')
button(class="pet-button Pet-{{pet.name}}-{{potion.name}}", ng-show='hasPet(pet.name, potion.name)', ng-class="{active: isCurrentPet(pet.name, potion.name)}", ng-click='choosePet(pet.name, potion.name)')
button(class="pet-button pet-not-owned", ng-hide='hasPet(pet.name, potion.name)')
img(src='/bower_components/habitrpg-shared/img/PixelPaw.png')
h4 Rare Pets
menu
div(ng-if='hasPet("Wolf", "Veteran")')
button(class="pet-button Pet-Wolf-Veteran", ng-class='{active: isCurrentPet("Wolf", "Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf')
div(ng-if='hasPet("Wolf", "Cerberus")')
button(class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup')

View File

@@ -1,9 +1,8 @@
.row-fluid(ng-controller='UserCtrl') script(id='partials/options.profile.avatar.html', type='text/ng-template')
.row-fluid
// ---- Customize -----
.span4.border-right .span4.border-right
menu(type='list') menu(type='list')
// gender // body-type
li.customize-menu li.customize-menu
menu(label='Head') menu(label='Head')
menu menu
@@ -12,8 +11,14 @@
label.checkbox label.checkbox
input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='toggleHelm(user.preferences.showHelm)') input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='toggleHelm(user.preferences.showHelm)')
| Show Helm | Show Helm
hr
menu(ng-show='user.preferences.gender=="f"', type='list')
li.customize-menu
menu(label='Clothing')
button.f_armor_0_v1.customize-option(type='button', ng-click='set("preferences.armorSet","v1")')
button.f_armor_0_v2.customize-option(type='button', ng-click='set("preferences.armorSet","v2")')
.span4.border-right
// hair // hair
li.customize-menu li.customize-menu
menu(label='Hair') menu(label='Hair')
@@ -22,8 +27,8 @@
button(class='{{user.preferences.gender}}_hair_brown customize-option', type='button', ng-click='set("preferences.hair","brown")') button(class='{{user.preferences.gender}}_hair_brown customize-option', type='button', ng-click='set("preferences.hair","brown")')
button(class='{{user.preferences.gender}}_hair_white customize-option', type='button', ng-click='set("preferences.hair","white")') button(class='{{user.preferences.gender}}_hair_white customize-option', type='button', ng-click='set("preferences.hair","white")')
button(class='{{user.preferences.gender}}_hair_red customize-option', type='button', ng-click='set("preferences.hair","red")') button(class='{{user.preferences.gender}}_hair_red customize-option', type='button', ng-click='set("preferences.hair","red")')
hr
.span4.border-right
// skin // skin
li.customize-menu li.customize-menu
menu(label='Basic Skins') menu(label='Basic Skins')
@@ -68,19 +73,14 @@
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_shadow', ng-class='{locked: !user.purchased.skin.shadow}', ng-click='unlock("skin.shadow")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_shadow', ng-class='{locked: !user.purchased.skin.shadow}', ng-click='unlock("skin.shadow")')
button.btn.btn-small.btn-primary(ng-hide='user.purchased.skin.monster && user.purchased.skin.pumpkin && user.purchased.skin.skeleton && user.purchased.skin.zombie && user.purchased.skin.ghost && user.purchased.skin.shadow', ng-click='unlock(["skin.monster", "skin.pumpkin", "skin.skeleton", "skin.zombie", "skin.ghost", "skin.shadow"])') Unlock Set - 5<span class="Pet_Currency_Gem1x inline-gems"/> button.btn.btn-small.btn-primary(ng-hide='user.purchased.skin.monster && user.purchased.skin.pumpkin && user.purchased.skin.skeleton && user.purchased.skin.zombie && user.purchased.skin.ghost && user.purchased.skin.shadow', ng-click='unlock(["skin.monster", "skin.pumpkin", "skin.skeleton", "skin.zombie", "skin.ghost", "skin.shadow"])') Unlock Set - 5<span class="Pet_Currency_Gem1x inline-gems"/>
script(id='partials/options.profile.stats.html', type='text/ng-template')
menu(ng-show='user.preferences.gender=="f"', type='list') .row-fluid
li.customize-menu .span6.border-right
menu(label='Clothing')
button.f_armor_0_v1.customize-option(type='button', ng-click='set("preferences.armorSet","v1")')
button.f_armor_0_v2.customize-option(type='button', ng-click='set("preferences.armorSet","v2")')
// ------ Stats ------
.span4.border-right
include ../shared/profiles/stats include ../shared/profiles/stats
.span6.border-right
include ../shared/profiles/achievements
// ------- Edit ------- script(id='partials/options.profile.profile.html', type='text/ng-template')
.span4
button.btn.btn-default(ng-click='_editing.profile = true', ng-show='!_editing.profile') Edit button.btn.btn-default(ng-click='_editing.profile = true', ng-show='!_editing.profile') Edit
button.btn.btn-primary(ng-click='save()', ng-show='_editing.profile') Save button.btn.btn-primary(ng-click='save()', ng-show='_editing.profile') Save
div(ng-show='!_editing.profile') div(ng-show='!_editing.profile')
@@ -115,6 +115,7 @@
.control-group.option-large .control-group.option-large
label.control-label Blurb label.control-label Blurb
textarea.option-content(style='height:15em;', placeholder='Blurb', ng-model='editingProfile.blurb') textarea.option-content(style='height:15em;', placeholder='Blurb', ng-model='editingProfile.blurb')
br
include ../shared/formatting-help include ../shared/formatting-help
.control-group.option-large .control-group.option-large
label.control-label Websites label.control-label Websites
@@ -126,3 +127,19 @@
| {{website}} | {{website}}
a(ng-click='removeWebsite($index)') a(ng-click='removeWebsite($index)')
i.icon-remove i.icon-remove
script(id='partials/options.profile.html', type="text/ng-template")
ul.nav.nav-tabs
li(ng-class="{ active: $state.includes('options.profile.avatar') }")
a(ui-sref='options.profile.avatar')
| Avatar
li(ng-class="{ active: $state.includes('options.profile.stats') }")
a(ui-sref='options.profile.stats')
| Stats & Achievements
li(ng-class="{ active: $state.includes('options.profile.profile') }")
a(ui-sref='options.profile.profile')
| Profile
.tab-content
.tab-pane.active
div(ui-view)

View File

@@ -1,4 +1,5 @@
.row-fluid(ng-controller='SettingsCtrl') script(type='text/ng-template', id='partials/options.settings.html')
.row-fluid
.personal-options.span6.border-right .personal-options.span6.border-right
h2 Settings h2 Settings
h4 Custom Day Start h4 Custom Day Start