Skip to content

Commit e1a57ec

Browse files
author
Jeffrey Biles
committed
Merge branch 'course-outline-start'
2 parents ea80fa5 + 668ea06 commit e1a57ec

File tree

13 files changed

+943
-676
lines changed

13 files changed

+943
-676
lines changed

db.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
},
1212
{
1313
"id": 2,
14-
"from": "jeffrey@vuescreencasts.com",
15-
"subject": "Five new VueJS videos this week + new podcast episode",
16-
"body": "I hope you've been enjoying the Vue 3 course I've been releasing with Vue Mastery!\n\nThis week on VueScreencasts.com we have a follow-up video that digs further into what we covered in this week's Vue Mastery lesson, I answer a question that five of you asked about last week's most popular video, and we start a new series with a very awesome library author.\n\nFinally, for your ears only: a new episode of Exploring the Vueniverse.",
17-
"sentAt": "2020-05-03T18:25:43.511Z",
14+
"from": "jeffrey@vuetraining.net",
15+
"subject": "Learn by doing - Vue 3 Zero to Intermediate in 8 weeks",
16+
"body": "Building projects is one of the most effective ways to learn - and _the_ most effective way _remember_ what you've learned - but it can be frustrating.\n\nThis 8-week course takes the pain out of 'learning by doing'.\n\nEach week we give you\n\n* a project that will grow your skills without overwhelming you\n* links to hand-picked resources, such as Vue Mastery videos, that share the knowledge you'll need for the project (no more useless rabbit holes)\n* answers to any and all questions you have while working\n* feedback on your completed code (so you're only learning good habits)\n\nOur instructors are standing by to answer your questions.\n\nReady to learn?",
17+
"sentAt": "2020-05-20T18:25:43.511Z",
1818
"archived": false,
1919
"read": false
2020
},

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
"core-js": "^3.6.4",
1313
"date-fns": "^2.11.0",
1414
"marked": "^0.8.1",
15-
"vue": "^3.0.0-alpha.10"
15+
"vue": "^3.0.0-beta.10"
1616
},
1717
"devDependencies": {
18-
"@vue/cli-plugin-babel": "^4.2.0",
19-
"@vue/cli-service": "^4.2.0",
20-
"@vue/compiler-sfc": "^3.0.0-alpha.10",
18+
"@vue/cli-plugin-babel": "^4.3.0",
19+
"@vue/cli-service": "^4.3.0",
20+
"@vue/compiler-sfc": "^3.0.0-beta.10",
2121
"faker": "^4.1.0",
22-
"vue-cli-plugin-vue-next": "^0.0.4",
22+
"vue-cli-plugin-vue-next": "^0.1.2",
2323
"vue-template-compiler": "^2.6.11"
2424
}
2525
}

src/App.vue

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,23 @@
11
<template>
2-
<div id="app">
3-
<button @click="selectScreen('MailScreenInbox');"
4-
:disabled="screenName == 'MailScreenInbox'">
5-
Inbox View
6-
</button>
7-
<button @click="selectScreen('MailScreenArchived')"
8-
:disabled="screenName == 'MailScreenArchived'">
9-
Archived View
10-
</button>
11-
12-
<suspense>
2+
<div id="app">
3+
<Suspense>
134
<template #default>
14-
<MailScreen :screenName="screenName" />
5+
<MailScreen />
156
</template>
167
<template #fallback>
17-
<p>Loading...</p>
8+
Loading...
189
</template>
19-
</suspense>
10+
</Suspense>
2011
</div>
2112
</template>
2213

2314
<script>
2415
import MailScreen from '@/components/MailScreen.vue';
25-
import useEmailSelection from './composition/useEmailSelection';
26-
import { ref } from 'vue'
2716
2817
export default {
2918
name: 'App',
3019
components: {
3120
MailScreen
32-
},
33-
setup(){
34-
let screenName = ref('MailScreenInbox');
35-
let {emailSelection} = useEmailSelection();
36-
let selectScreen = function(newScreen){
37-
screenName.value = newScreen;
38-
emailSelection.clear();
39-
}
40-
return {screenName, selectScreen}
4121
}
4222
};
4323
</script>
@@ -66,6 +46,13 @@ button:disabled {
6646
cursor: auto;
6747
}
6848
49+
button.selected {
50+
cursor: auto;
51+
color: black;
52+
border-color: black;
53+
border-width: 2px;
54+
}
55+
6956
.clickable {
7057
cursor: pointer;
7158
}

src/components/BulkActionBar.vue

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,77 @@
11
<template>
22
<div class="bulk-action-bar">
33
<span class="checkbox">
4-
<input type="checkbox" :checked="allAreSelected" @click="bulkSelect">
5-
<span v-if="!allAreSelected && numberSelected > 0">-</span> <!-- later on this minus sign will be in the checkbox, as it is in gmail -->
4+
<input type="checkbox"
5+
:checked="allAreSelected"
6+
:class="[partialSelection ? 'partial-check' : '']"
7+
@click="bulkSelect">
68
</span>
79

810
<span class="buttons">
911
<button @click="emailSelection.markRead()"
10-
:disabled="Array.from(emailSelection.emails).every(e => e.read)"
11-
v-if="actions.includes('markRead')">
12+
:disabled="Array.from(emailSelection.emails).every(e => e.read)">
1213
Mark Read
1314
</button>
1415
<button @click="emailSelection.markUnread()"
15-
:disabled="Array.from(emailSelection.emails).every(e => !e.read)"
16-
v-if="actions.includes('markUnread')">
16+
:disabled="Array.from(emailSelection.emails).every(e => !e.read)">
1717
Mark Unread
1818
</button>
19-
<button @click="emailSelection.archive()"
20-
:disabled="numberSelected == 0"
21-
v-if="actions.includes('archive')">
19+
<button v-if="selectedScreen == 'inbox'"
20+
@click="emailSelection.archive()"
21+
:disabled="numberSelected == 0">
2222
Archive
2323
</button>
24-
<button @click="emailSelection.moveToInbox()"
25-
:disabled="numberSelected == 0"
26-
v-if="actions.includes('moveToInbox')">
24+
<button v-else
25+
@click="emailSelection.moveToInbox()"
26+
:disabled="numberSelected == 0">
2727
Move to Inbox
2828
</button>
2929
</span>
3030
</div>
3131
</template>
3232

3333
<script>
34-
import useEmailSelection from '../composition/useEmailSelection';
34+
import { useEmailSelection } from '../composition/useEmailSelection';
3535
import { computed } from 'vue';
3636
3737
export default {
38-
setup({emails}){
39-
let {emailSelection} = useEmailSelection();
38+
setup(props){
39+
let emailSelection = useEmailSelection();
40+
4041
let numberSelected = computed(() => {
4142
return emailSelection.emails.size;
4243
})
4344
let allAreSelected = computed(() => {
44-
return emails.length == numberSelected.value;
45+
return props.emails.length == numberSelected.value && numberSelected.value !== 0;
46+
})
47+
let partialSelection = computed(() => {
48+
return numberSelected.value > 0 && !allAreSelected.value;
4549
})
4650
4751
let bulkSelect = function(){
4852
if(allAreSelected.value) {
4953
emailSelection.clear();
5054
} else {
51-
emailSelection.addMultiple(emails)
55+
emailSelection.addMultiple(props.emails)
5256
}
5357
}
54-
return { emailSelection, allAreSelected, bulkSelect, numberSelected }
58+
59+
return {
60+
partialSelection,
61+
allAreSelected,
62+
bulkSelect,
63+
emailSelection,
64+
numberSelected
65+
}
5566
},
5667
props: {
5768
emails: {
5869
type: Array,
59-
default: []
60-
},
61-
actions: {
62-
type: Array,
63-
default: ['markRead', 'markUnread']
70+
required: true
71+
},
72+
selectedScreen: {
73+
type: String,
74+
required: true
6475
}
6576
}
6677
}

src/components/MailScreen.vue

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,73 @@
11
<template>
2-
<div>
3-
<component :is="screenName" :emails="emails.sort((e1, e2) => e1.sentAt < e2.sentAt ? 1 : -1)" />
4-
</div>
2+
<button @click="selectScreen('inbox');"
3+
:class="[selectedScreen == 'inbox' ? 'selected' : '']">
4+
Inbox View
5+
</button>
6+
<button @click="selectScreen('archive')"
7+
:class="[selectedScreen == 'archive' ? 'selected' : '']">
8+
Archived View
9+
</button>
10+
11+
<h1>VMail {{capitalize(selectedScreen)}}</h1>
12+
13+
<BulkActionBar :emails="filteredEmails"
14+
:selectedScreen="selectedScreen" />
15+
16+
<MailTable :emails="filteredEmails" />
517
</template>
618

719
<script>
8-
import MailScreenArchived from '@/components/MailScreenArchived.vue';
9-
import MailScreenInbox from '@/components/MailScreenInbox.vue';
10-
import { ref } from 'vue';
1120
import axios from 'axios';
1221
22+
import MailTable from '@/components/MailTable.vue';
23+
import BulkActionBar from '@/components/BulkActionBar.vue';
24+
import { useEmailSelection } from '../composition/useEmailSelection';
25+
1326
export default {
1427
async setup(){
15-
let {data} = await axios.get('http://localhost:3000/emails');
16-
let emails = ref(data);
28+
let response = await axios.get('http://localhost:3000/emails');
29+
let emails = response.data;
30+
let selectedScreen = 'inbox';
1731
18-
return {emails};
32+
return {
33+
emails,
34+
selectedScreen,
35+
emailSelection: useEmailSelection()
36+
}
1937
},
2038
components: {
21-
MailScreenArchived,
22-
MailScreenInbox
39+
BulkActionBar,
40+
MailTable
41+
},
42+
methods: {
43+
selectScreen(newScreen) {
44+
this.selectedScreen = newScreen;
45+
this.emailSelection.clear();
46+
},
47+
capitalize(word) {
48+
if(!word || !word.length){ return; }
49+
50+
return word[0].toUpperCase() + word.slice(1)
51+
}
2352
},
24-
props: {
25-
screenName: {
26-
type: String,
27-
required: true
53+
computed: {
54+
sortedEmails(){
55+
return this.emails.sort((e1, e2) => {
56+
return e1.sentAt < e2.sentAt ? 1 : -1
57+
})
58+
},
59+
unarchivedEmails(){
60+
return this.sortedEmails.filter(e => !e.archived)
61+
},
62+
archivedEmails(){
63+
return this.sortedEmails.filter(e => e.archived)
64+
},
65+
filteredEmails(){
66+
let filters = {
67+
inbox: this.unarchivedEmails,
68+
archive: this.archivedEmails
69+
}
70+
return filters[this.selectedScreen]
2871
}
2972
}
3073
}

src/components/MailScreenArchived.vue

Lines changed: 0 additions & 34 deletions
This file was deleted.

src/components/MailScreenInbox.vue

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)