Skip to content

Commit

Permalink
feat(ui): Login and setup flow have been implemented
Browse files Browse the repository at this point in the history
Also,
- Fixed empty dashboard refresh
- GPX download loading state
  • Loading branch information
bahattincinic committed Jun 5, 2024
1 parent c2f0488 commit d91c295
Show file tree
Hide file tree
Showing 29 changed files with 925 additions and 604 deletions.
7 changes: 4 additions & 3 deletions api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,17 @@ func (a *API) updateConfig(c echo.Context) error {
// @Summary Check Application Setup completed
// @Tags config
// @Accept json
// @Success 200 {object} map[string]bool
// @Success 200 {object} map[string]interface{}
// @Router /api/config/setup [get]
func (a *API) checkSetupCompleted(c echo.Context) error {
cfg, err := a.db.GetCurrentConfig()
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err)
}

return c.JSON(http.StatusOK, map[string]bool{
"status": cfg.SetupCompleted(),
return c.JSON(http.StatusOK, map[string]interface{}{
"completed": cfg.SetupCompleted(),
"login_type": cfg.LoginType,
})
}

Expand Down
2 changes: 1 addition & 1 deletion api/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func (a *API) createComponent(c echo.Context) error {

type componentInput struct {
Name string `json:"name" validate:"required" err:"name is required"`
Type models.ComponentType `json:"type" validate:"type" err:"name is required"`
Type models.ComponentType `json:"type" validate:"required" err:"name is required"`
Configs interface{} `json:"configs"`
Query string `json:"query" validate:"required" err:"query is required"`
}
Expand Down
4 changes: 1 addition & 3 deletions api/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,7 @@ const docTemplate = `{
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": {
"type": "boolean"
}
"additionalProperties": true
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions api/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,7 @@
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": {
"type": "boolean"
}
"additionalProperties": true
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions api/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -711,8 +711,7 @@ paths:
"200":
description: OK
schema:
additionalProperties:
type: boolean
additionalProperties: true
type: object
summary: Check Application Setup completed
tags:
Expand Down
13 changes: 12 additions & 1 deletion ui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div id="app">
<Toast />
<ConfirmDialog />
<AppHeader />
<AppHeader v-if="showHeader" />
<router-view />
</div>
</template>
Expand All @@ -11,12 +11,23 @@
import Toast from 'primevue/toast';
import ConfirmDialog from 'primevue/confirmdialog';
import AppHeader from './components/AppHeader.vue';
import { useUserStore } from '@/store/user';
export default {
components: {
AppHeader,
Toast,
ConfirmDialog,
},
setup() {
return {
user: useUserStore(),
};
},
computed: {
showHeader() {
return !['Login', 'Setup'].includes(this.$route.name);
},
},
};
</script>
52 changes: 29 additions & 23 deletions ui/src/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<script>
import Menubar from 'primevue/menubar';
import { useRouter } from 'vue-router';
import { useStravaStore } from '@/store/strava';
import { useUserStore } from '@/store/user';
export default {
Expand All @@ -15,26 +15,26 @@ export default {
Menubar,
},
setup() {
const router = useRouter();
const user = useUserStore();
return { router, user };
return {
strava: useStravaStore(),
user: useUserStore(),
};
},
computed: {
items() {
const accessToken = this.user.accessToken;
const user = this.user.user;
const accessToken = this.strava.accessToken;
const user = this.strava.user;
return [
{
label: 'Dashboard',
icon: 'pi pi-fw pi-home',
command: () => this.router.push('/'),
command: () => this.$router.push('/'),
},
{
label: 'Settings',
icon: 'pi pi-fw pi-cog',
command: () => this.router.push('/app/settings'),
command: () => this.$router.push('/app/settings'),
},
{
label: 'Data',
Expand All @@ -43,49 +43,55 @@ export default {
{
label: 'Activities',
icon: 'pi pi-fw pi-calendar',
command: () => this.router.push('/app/activities'),
command: () => this.$router.push('/app/activities'),
},
{
label: 'Gears',
icon: 'pi pi-fw pi-sitemap',
command: () => this.router.push('/app/gears'),
command: () => this.$router.push('/app/gears'),
},
{
label: 'Athletes',
icon: 'pi pi-fw pi-user',
command: () => this.router.push('/app/athletes'),
command: () => this.$router.push('/app/athletes'),
},
],
},
{
label: accessToken ? user.firstname : 'Anonymous',
label: accessToken ? user.firstname : 'User',
icon: 'pi pi-fw pi-user',
items: [
...(this.user.loginNeeded()
? [
{
label: 'Logout App',
icon: 'pi pi-fw pi-sign-out',
command: () => {
this.user.logout();
this.$router.push('/app/login');
},
},
]
: []),
...(accessToken
? [
{
label: 'Logout',
label: 'Logout Strava',
icon: 'pi pi-fw pi-sign-out',
command: () => this.logout(),
command: () => this.strava.logout(),
},
]
: [
{
label: 'Login',
label: 'Login Strava',
icon: 'pi pi-fw pi-sign-in',
command: () => this.router.push('/app/login'),
command: () => this.$router.push('/app/strava-login'),
},
]),
],
},
];
},
},
methods: {
logout() {
const user = useUserStore();
user.logout();
},
},
};
</script>
7 changes: 6 additions & 1 deletion ui/src/components/ComponentModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ export default {
type: Boolean,
default: false,
},
accessToken: {
type: String,
required: true,
},
},
components: {
Dialog,
Expand Down Expand Up @@ -303,7 +307,8 @@ export default {
this.$emit('set-loading', true);
const task = await waitAsyncTask(
await runQuery({
this.accessToken,
await runQuery(this.accessToken, {
query: this.form.query,
})
);
Expand Down
41 changes: 28 additions & 13 deletions ui/src/pages/ActivitiesPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@
:style="{ width: '50rem' }"
>
<div class="mb-3">
<Message v-if="!strava.accessToken" severity="info">
To download GPX file, you need to logged in to with Strava
</Message>
<Button
:disabled="!accessToken || loading"
:disabled="!strava.accessToken || loading || modal.loading"
type="button"
label="Download GPX"
severity="secondary"
@click="downloadGPXFile"
v-tooltip.right="
'To download GPX file, you need to logged in to with Strava'
"
/>
</div>
<div>
Expand All @@ -63,8 +63,9 @@ import Skeleton from 'primevue/skeleton';
import VueJsonPretty from 'vue-json-pretty';
import Dialog from 'primevue/dialog';
import Button from 'primevue/button';
import Message from 'primevue/message';
import { useHead } from '@unhead/vue';
import { mapState } from 'pinia';
import { useStravaStore } from '@/store/strava';
import { useUserStore } from '@/store/user';
export default {
Expand All @@ -77,9 +78,15 @@ export default {
Button,
VueJsonPretty,
Skeleton,
Message,
},
setup() {
useHead({ title: 'Activities' });
return {
strava: useStravaStore(),
user: useUserStore(),
};
},
data() {
return {
Expand All @@ -88,6 +95,7 @@ export default {
currentPage: 1,
count: 0,
modal: {
loading: false,
show: false,
data: {},
},
Expand All @@ -96,9 +104,6 @@ export default {
mounted() {
this.fetch();
},
computed: {
...mapState(useUserStore, ['accessToken']),
},
methods: {
athleteName(row) {
return `${row.athlete.firstname} ${row.athlete.lastname}`;
Expand All @@ -110,7 +115,10 @@ export default {
async fetch() {
try {
this.loading = true;
const response = await fetchActivities(this.currentPage);
const response = await fetchActivities(
this.user.accessToken,
this.currentPage
);
this.activities = response.results;
this.count = response.count;
} catch (error) {
Expand All @@ -121,11 +129,17 @@ export default {
},
async downloadGPXFile() {
try {
this.loading = true;
const fileName = `activity_${this.modal.data.id}.gpx`;
this.modal.loading = true;
const blob = await getActivityGPX(
this.modal.data.id,
this.strava.accessToken,
this.user.accessToken
);
const blob = await getActivityGPX(this.modal.data.id, this.accessToken);
const fileName = `activity_${this.modal.data.id}.gpx`;
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
Expand All @@ -135,7 +149,7 @@ export default {
} catch (error) {
this.onError(error);
} finally {
this.loading = false;
this.modal.loading = false;
}
},
onError(err) {
Expand All @@ -149,6 +163,7 @@ export default {
onRowSelect(event) {
this.modal.data = event.data;
this.modal.show = true;
this.modal.loading = false;
},
},
};
Expand Down
10 changes: 9 additions & 1 deletion ui/src/pages/AthletesPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import VueJsonPretty from 'vue-json-pretty';
import Dialog from 'primevue/dialog';
import { useHead } from '@unhead/vue';
import Skeleton from 'primevue/skeleton';
import { useUserStore } from '@/store/user';
export default {
name: 'AthletesPage',
Expand All @@ -62,6 +63,10 @@ export default {
},
setup() {
useHead({ title: 'Athletes' });
return {
user: useUserStore(),
};
},
data() {
return {
Expand All @@ -86,7 +91,10 @@ export default {
async fetch() {
try {
this.loading = true;
const response = await fetchAthletes(this.currentPage);
const response = await fetchAthletes(
this.user.accessToken,
this.currentPage
);
this.athletes = response.results;
this.count = response.count;
} catch (error) {
Expand Down
Loading

0 comments on commit d91c295

Please sign in to comment.