Skip to content

Commit

Permalink
Merge branch 'master' into attachments-modal
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-white committed Nov 1, 2018
2 parents a569202 + c6fd4ee commit c653fdb
Show file tree
Hide file tree
Showing 50 changed files with 2,079 additions and 1,040 deletions.
8 changes: 6 additions & 2 deletions assets/scss/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ except according to the terms contained in the LICENSE file.
*/

// Core
$color-text: #333;
$color-accent-primary: #bd006b;
$color-accent-secondary: #8d0050;
$color-page-background: #f7f7f7;

// Text
$color-text: #333;
$color-text-muted: #999;

// Contextual colors
$color-success: #0d840f;
$color-success-light: #ddf1d5;
Expand All @@ -32,7 +35,8 @@ $color-action-foreground: #0c7bd1;
$color-action-background: #009ecc;
$color-action-background-hover: #0086ad;
$color-input-inactive: #666;
$color-input-background: #f7f7f7;
$color-input-background: #eee;
$color-panel-input-background: #f7f7f7;

// Tables
$margin-bottom-table: 20px;
Expand Down
49 changes: 49 additions & 0 deletions lib/components/account/edit.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!--
Copyright 2017 ODK Central Developers
See the NOTICE file at the top-level directory of this distribution and at
https://github.com/opendatakit/central-frontend/blob/master/NOTICE.

This file is part of ODK Central. It is subject to the license terms in
the LICENSE file found in the top-level directory of this distribution and at
https://www.apache.org/licenses/LICENSE-2.0. No part of ODK Central,
including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
<template>
<div>
<page-head>
<template slot="title">{{ displayName }}</template>
</page-head>
<page-body>
<div class="row">
<div class="col-xs-7">
<form-edit-basic-details @update:session="afterUpdateSession"/>
</div>
<div class="col-xs-5">
<form-edit-password/>
</div>
</div>
</page-body>
</div>
</template>

<script>
import FormEditBasicDetails from './edit/basic-details.vue';
import FormEditPassword from './edit/password.vue';

export default {
name: 'AccountEdit',
components: { FormEditBasicDetails, FormEditPassword },
data() {
return {
displayName: this.$session.user.displayName
};
},
methods: {
afterUpdateSession() {
this.displayName = this.$session.user.displayName;
this.$emit('update:session');
}
}
};
</script>
64 changes: 64 additions & 0 deletions lib/components/account/edit/basic-details.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<!--
Copyright 2017 ODK Central Developers
See the NOTICE file at the top-level directory of this distribution and at
https://github.com/opendatakit/central-frontend/blob/master/NOTICE.

This file is part of ODK Central. It is subject to the license terms in
the LICENSE file found in the top-level directory of this distribution and at
https://www.apache.org/licenses/LICENSE-2.0. No part of ODK Central,
including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
<template>
<div id="account-edit-basic-details" class="panel panel-simple">
<div class="panel-heading"><h1 class="panel-title">Basic Details</h1></div>
<div class="panel-body">
<form @submit="submit">
<label class="form-group">
<input v-model.trim="email" type="email" class="form-control"
placeholder="Email address *" required>
<span class="form-label">Email address *</span>
</label>
<label class="form-group">
<input v-model.trim="displayName" type="text" class="form-control"
placeholder="Display name *" required>
<span class="form-label">Display name *</span>
</label>
<button :disabled="awaitingResponse" type="submit"
class="btn btn-primary">
Update details <spinner :state="awaitingResponse"/>
</button>
</form>
</div>
</div>
</template>

<script>
import request from '../../../mixins/request';
import { logIn } from '../../../session';

export default {
name: 'FormEditBasicDetails',
mixins: [request()],
data() {
return {
requestId: null,
email: this.$session.user.email,
displayName: this.$session.user.displayName
};
},
methods: {
submit() {
const data = { email: this.email, displayName: this.displayName };
this.patch(`/users/${this.$session.user.id}`, data)
.then(response => {
const { token, expiresAt } = this.$session;
logIn({ token, expiresAt }, response.data);
this.$emit('update:session');
this.$alert().success('Success! Your user details have been updated.');
})
.catch(() => {});
}
}
};
</script>
77 changes: 77 additions & 0 deletions lib/components/account/edit/password.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!--
Copyright 2017 ODK Central Developers
See the NOTICE file at the top-level directory of this distribution and at
https://github.com/opendatakit/central-frontend/blob/master/NOTICE.

This file is part of ODK Central. It is subject to the license terms in
the LICENSE file found in the top-level directory of this distribution and at
https://www.apache.org/licenses/LICENSE-2.0. No part of ODK Central,
including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
<template>
<div id="account-edit-password" class="panel panel-simple">
<div class="panel-heading">
<h1 class="panel-title">Change Password</h1>
</div>
<div class="panel-body">
<form @submit="submit">
<label class="form-group">
<input id="form-edit-password-old-password" v-model="oldPassword"
type="password" class="form-control" placeholder="Old password *"
required>
<span class="form-label">Old password *</span>
</label>
<label :class="{ 'has-error': mismatch }" class="form-group">
<input id="form-edit-password-new-password" v-model="newPassword"
type="password" class="form-control" placeholder="New password *"
required>
<span class="form-label">New password *</span>
</label>
<label :class="{ 'has-error': mismatch }" class="form-group">
<input id="form-edit-password-confirm" v-model="confirm"
type="password" class="form-control"
placeholder="New password (confirm) *" required>
<span class="form-label">New password (confirm) *</span>
</label>
<button :disabled="awaitingResponse" type="submit"
class="btn btn-primary">
Change password <spinner :state="awaitingResponse"/>
</button>
</form>
</div>
</div>
</template>

<script>
import request from '../../../mixins/request';

export default {
name: 'FormEditPassword',
mixins: [request()],
data() {
return {
requestId: null,
oldPassword: '',
newPassword: '',
confirm: '',
mismatch: false
};
},
methods: {
submit() {
this.mismatch = this.newPassword !== this.confirm;
if (this.mismatch) {
this.$alert().danger('Please check that your new passwords match.');
return;
}
const data = { old: this.oldPassword, new: this.newPassword };
this.put(`/users/${this.$session.user.id}/password`, data)
.then(() => {
this.$alert().success('Success! Your password has been updated.');
})
.catch(() => {});
}
}
};
</script>
6 changes: 4 additions & 2 deletions lib/components/account/login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ export default {
this
.post('/sessions', { email: this.email, password: this.password })
.then(({ data }) => this.fetchUser(data))
.then(({ session, user }) => logIn(session, user))
.then(() => this.routeToNext())
.then(({ session, user }) => {
logIn(session, user);
this.routeToNext();
})
.catch(() => {
this.disabled = false;
});
Expand Down
75 changes: 64 additions & 11 deletions lib/components/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ except according to the terms contained in the LICENSE file.
<!-- Do not show the navbar until the first time a navigation is confirmed.
The user's session may change during that time, affecting how the navbar is
rendered. -->
<navbar v-show="firstNavigationConfirmed"/>
<navbar v-show="firstNavigationConfirmed" :session="session"/>
<alert id="app-alert" v-bind="alert" @close="alert.state = false"/>
<div class="container-fluid">
<router-view/>
<router-view @update:session="updateSession"/>
</div>
</div>
</template>
Expand All @@ -35,13 +35,27 @@ export default {
/* Vue seems to trigger the initial navigation before creating App. If the
initial navigation is synchronous, Vue seems to confirm the navigation
before creating App -- in which case firstNavigationConfirmed will be
initialized to true and the $route() watcher will not be called until the
initialized to true and the $route watcher will not be called until the
user navigates elsewhere. However, if the initial navigation is
asynchronous, Vue seems to create App before waiting to confirm the
navigation. In that case, firstNavigationConfirmed will be initialized to
false and the $route() watcher will be called once the initial navigation
is confirmed. */
false and the $route watcher will be called once the initial navigation is
confirmed. */
firstNavigationConfirmed: routerState.navigations.first.confirmed,
/*
this.$session is not a reactive property, so we store a copy of it here in
order to pass it to Navbar. This copy can change in one of two ways:

1. The router changes $session along with $route. App watches for
changes to $route, which is a reactive property.
2. The router view changes $session, then notes the change by triggering
an update:session event.

Between the router, session, and alert, App is doing a fair amount of
global state management at this point. We may end up wanting to implement
a more comprehensive state management strategy.
*/
session: this.$session,
alert: blankAlert()
};
},
Expand All @@ -51,12 +65,19 @@ export default {
}
},
watch: {
$route() {
this.firstNavigationConfirmed = true;
this.session = this.$session;
},
// Using a strategy similar to the one here:
// https://github.com/vuejs/vue/issues/844
routeAndAlert([currentRoute, currentAlert], [previousRoute, previousAlert]) {
if (currentRoute === previousRoute) return;
this.firstNavigationConfirmed = true;
if (currentAlert === previousAlert && this.alert.state)
// If both the route and alert have changed, the router view will be
// updated, and if the new alert is visible, it will be shown. On the
// other hand, if only the route has changed, then if there is an alert
// currently visible, it will be hidden.
if (currentRoute !== previousRoute && currentAlert === previousAlert &&
this.alert.state)
this.alert.state = false;
}
},
Expand All @@ -66,6 +87,11 @@ export default {
$(this.$refs.app).on('click', 'a.disabled', (event) => {
event.preventDefault();
});
},
methods: {
updateSession() {
this.session = this.$session;
}
}
};
</script>
Expand Down Expand Up @@ -123,7 +149,7 @@ h1 {
}

.text-muted {
color: #999;
color: $color-text-muted;
}

.text-success {
Expand Down Expand Up @@ -222,7 +248,7 @@ a:hover, a:focus {
font-weight: normal;
padding-bottom: 15px;

input, select {
.form-control {
background: $color-input-background;
border: none;
border-bottom: 1px solid $color-input-inactive;
Expand All @@ -245,7 +271,7 @@ a:hover, a:focus {
}

&:placeholder-shown + .form-label {
transform: translateY(-13px);
transform: translateY(-15px);
}
}

Expand All @@ -264,6 +290,29 @@ a:hover, a:focus {
cursor: default;
}

.has-error {
.form-label,
.radio,
.checkbox,
&.radio label,
&.checkbox label {
color: $color-danger;
}

.form-control {
border-color: $color-danger;

&:focus {
border-color: $color-danger-dark;
box-shadow: none;

+ .form-label {
color: $color-danger-dark;
}
}
}
}

.table {
margin-bottom: $margin-bottom-table;

Expand Down Expand Up @@ -345,6 +394,10 @@ a:hover, a:focus {

.panel-body {
padding: 25px 15px;

.form-group .form-control {
background-color: $color-panel-input-background;
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions lib/components/form/attachment/list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ export default {
modal(['uploadFilesModal', 'nameMismatch']),
request()
],
// Setting this in order to ignore attributes from FormShow that are intended
// for other form-related components.
inheritAttrs: false,
props: {
form: {
type: Object,
Expand Down
2 changes: 1 addition & 1 deletion lib/components/form/new.vue
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export default {
@import '../../../assets/scss/variables';

#form-new-drop-zone {
background-color: $color-input-background;
background-color: $color-panel-input-background;
border: 1px dashed $color-subpanel-border;
padding-bottom: 15px;
padding-top: 15px;
Expand Down
Loading

0 comments on commit c653fdb

Please sign in to comment.