Skip to content
This repository was archived by the owner on Jul 27, 2024. It is now read-only.

Commit e48ad40

Browse files
committed
Add FE support for saving a course plan
1 parent 2602369 commit e48ad40

File tree

6 files changed

+324
-53
lines changed

6 files changed

+324
-53
lines changed

Closure_Front_End/src/App.vue

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
<router-link class="navbar-item" to="/"><b>Closure()</b></router-link>
77
</div>
88
<div class="navbar-start is-hidden-mobile is-hidden-touch">
9+
10+
<div v-if="currentCourseplan" class="navbar-item">
11+
<span>שם תכנית:
12+
{{ currentCourseplan.name}}
13+
</span>
14+
</div>
15+
<save-menu/>
16+
917
<div class="navbar-item">
1018
<div class="buttons">
1119
<router-link
@@ -50,15 +58,19 @@
5058
</nav>
5159

5260
<router-view />
61+
62+
<save-state-footer />
5363
</template>
5464

5565
<script>
5666
import ErrorNotification from './components/ErrorNotification.vue';
57-
58-
import { toRefs, reactive, onMounted, provide, inject, readonly } from 'vue';
67+
import SaveMenu from './components/SaveMenu.vue';
68+
import SaveStateFooter from './components/SaveStateFooter.vue';
69+
import { toRefs, reactive, onMounted, provide, inject, readonly} from 'vue';
70+
import { currentCourseplan } from '@/course-store.js'
5971
export default {
6072
name: "App",
61-
components: {ErrorNotification},
73+
components: {ErrorNotification, SaveMenu, SaveStateFooter},
6274
setup() {
6375
const state = reactive({
6476
student: null,
@@ -95,7 +107,7 @@ export default {
95107
});
96108
97109
return {
98-
...toRefs(state), login, logout, auth
110+
...toRefs(state), login, logout, auth, currentCourseplan
99111
}
100112
101113
}

Closure_Front_End/src/auth/index.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,22 +133,21 @@ export const routeGuard = (to, from, next) => {
133133
})
134134
}
135135

136+
export const http = axios.create({
137+
baseURL: import.meta.env.VITE_API_URL
138+
});
139+
window.closureAxios = http;
140+
136141
export const setupAuth = async (options, callbackRedirect) => {
137142
client = await createAuth0Client({
138143
...options,
139144
});
140145

141-
142-
let http = axios.create({
143-
baseURL: import.meta.env.VITE_API_URL
144-
});
145-
146146
http.interceptors.response.use((response) => response,
147147
function (error){
148148
errorHandler(error);
149149
return Promise.reject(error);
150150
});
151-
window.closureAxios = http;
152151

153152

154153
watchEffect(async () => {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<template>
2+
<div class="box" dir="rtl">
3+
<h1 class="title">שמירת תכנית לימודים</h1>
4+
<div class="field">
5+
<label class="label">שם תכנית</label>
6+
<div class="control">
7+
<input
8+
class="input"
9+
type="text"
10+
placeholder="שם התכנית"
11+
v-model="name"
12+
/>
13+
</div>
14+
</div>
15+
16+
<div class="field">
17+
<div class="control">
18+
<label class="checkbox">
19+
<input type="checkbox" v-model="publicize" />
20+
ציבורי
21+
</label>
22+
</div>
23+
</div>
24+
25+
<div class="field is-grouped">
26+
<div class="control">
27+
<button
28+
class="button is-link"
29+
:class="{ 'is-loading': saving }"
30+
@click="onSubmit"
31+
:disabled="!canSave || saving"
32+
>
33+
שמירה
34+
</button>
35+
</div>
36+
<div class="control">
37+
<button class="button is-link is-light" @click="$emit('close')">
38+
ביטול
39+
</button>
40+
</div>
41+
</div>
42+
</div>
43+
</template>
44+
45+
<script>
46+
import { reactive, computed, toRefs } from "vue";
47+
import { saveAs } from "@/course-store.js";
48+
export default {
49+
emits: ["close"],
50+
setup(_props, { emit }) {
51+
const state = reactive({
52+
name: "",
53+
publicize: false,
54+
saving: false,
55+
});
56+
57+
const onSubmit = async () => {
58+
state.saving = true;
59+
try {
60+
await saveAs({ name: state.name, publicize: state.publicize });
61+
emit("close");
62+
} finally {
63+
state.saving = false;
64+
}
65+
};
66+
67+
const canSave = computed(() => state.name.length > 0);
68+
return {
69+
...toRefs(state),
70+
canSave,
71+
onSubmit,
72+
};
73+
},
74+
};
75+
</script>
76+
77+
<style>
78+
</style>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<template>
2+
<div class="navbar-item has-dropdown is-hoverable" dir="rtl">
3+
<a class="navbar-link"> קובץ </a>
4+
5+
<div class="navbar-dropdown">
6+
<a class="navbar-item"> טעינה </a>
7+
<a v-if="!saving" class="navbar-item" :class="{'is-disabled': !canSave}" @click="onSave"> שמירה </a>
8+
<div class="navbar-item" v-if="saving">
9+
<button class="navbar-item button is-loading" v-if="saving" disabled>
10+
שמירה
11+
</button>
12+
</div>
13+
<a class="navbar-item" :class="{'is-disabled': !canSaveAs}" @click="displaySaveAs">
14+
שמירה בשם
15+
</a>
16+
<hr class="navbar-divider" />
17+
<a class="navbar-item"> שיתוף </a>
18+
</div>
19+
</div>
20+
<div class="modal" :class="{ 'is-active': showSaveAsMenu }">
21+
<div class="modal-background" @click="closeSaveAsMenu"></div>
22+
<div class="modal-content">
23+
<save-as-modal @close="closeSaveAsMenu" />
24+
</div>
25+
<button
26+
class="modal-close is-large"
27+
aria-label="close"
28+
@click="closeSaveAsMenu"
29+
></button>
30+
</div>
31+
</template>
32+
33+
<script>
34+
import { computed, ref } from "vue";
35+
import SaveAsModal from "@/components/SaveAsModal.vue";
36+
import { currentCourseplan, isDirty, save } from "@/course-store.js";
37+
export default {
38+
components: { SaveAsModal },
39+
setup() {
40+
const canSave = isDirty;
41+
const canSaveAs = computed(() => currentCourseplan.value !== null);
42+
const showSaveAsMenu = ref(false);
43+
44+
const displaySaveAs = () => {
45+
showSaveAsMenu.value = true;
46+
};
47+
const closeSaveAsMenu = () => (showSaveAsMenu.value = false);
48+
49+
const saving = ref(false);
50+
const onSave = async () => {
51+
if (currentCourseplan == null) {
52+
displaySaveAs();
53+
} else {
54+
saving.value = true;
55+
try {
56+
await save();
57+
} finally {
58+
saving.value = false;
59+
}
60+
}
61+
};
62+
63+
return {
64+
canSave,
65+
canSaveAs,
66+
showSaveAsMenu,
67+
onSave,
68+
displaySaveAs,
69+
closeSaveAsMenu,
70+
saving,
71+
};
72+
},
73+
};
74+
</script>
75+
76+
<style scoped>
77+
a.is-disabled {
78+
pointer-events: none;
79+
opacity: .65;
80+
}
81+
</style>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<template>
2+
<footer class="footer" dir="rtl">
3+
4+
<div class="content has-text-centered">
5+
{{ lastSaved }}
6+
<br/>
7+
מלוכלך:
8+
{{ isDirty }}
9+
</div>
10+
11+
<div class="content has-text-centered">
12+
<p>
13+
פרויקט
14+
<strong>Closure</strong>
15+
</p>
16+
</div>
17+
18+
<div class="content has-text-centered">
19+
<a class="button" href="https://github.com/scdor/closure">
20+
<span class="icon">
21+
<i class="fab fa-github"></i>
22+
</span>
23+
<span>GitHub</span>
24+
</a>
25+
</div>
26+
</footer>
27+
</template>
28+
29+
<script>
30+
import { computed } from 'vue'
31+
import { currentCourseplan, isDirty } from '@/course-store'
32+
export default {
33+
setup() {
34+
const lastSaved = computed(() => {
35+
if (currentCourseplan.value.modified_at) {
36+
const date = new Date(currentCourseplan.value.modified_at)
37+
return `נשמר לאחרונה ב${date.toLocaleString()}`
38+
}
39+
return "טרם נשמר"
40+
})
41+
return {
42+
isDirty, lastSaved
43+
}
44+
}
45+
};
46+
</script>
47+
48+
<style>
49+
</style>

0 commit comments

Comments
 (0)