608 lines
18 KiB
Markdown
608 lines
18 KiB
Markdown
# Firebase
|
|
|
|
API documentation (JS): <https://firebase.google.com/docs/reference/js>
|
|
Guides documentation: <https://firebase.google.com/docs/guides>
|
|
|
|
Handling errors
|
|
|
|
List of errors: <https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createuserwithemailandpassword>
|
|
|
|
You can catch the error and use if/else to capture the specific error.
|
|
|
|
```javascript
|
|
firebase
|
|
.auth()
|
|
.createUserWithEmailAndPassword(email, password)
|
|
.catch(function(error) {
|
|
// Handle Errors here.
|
|
var errorCode = error.code;
|
|
var errorMessage = error.message;
|
|
if (errorCode == "auth/weak-password") {
|
|
alert("The password is too weak.");
|
|
} else {
|
|
alert(errorMessage);
|
|
}
|
|
console.log(error);
|
|
});
|
|
```
|
|
|
|
Firebase User object:
|
|
<https://firebase.google.com/docs/reference/js/firebase.User>
|
|
|
|
All properties that it takes/available listed above
|
|
|
|
## Create new User
|
|
|
|
Use `firebase.auth().createUserWithEmailAndPassword(email, password)` to create a new user.
|
|
|
|
Only an email address and password is needed to create a new account. The user itself has a few additional attributes you can attach to it - the `displayName` and the `photoURL` among a few others. You can see all of them in the properties of the user object:
|
|
`https://firebase.google.com/docs/reference/js/firebase.User#properties`
|
|
|
|
Any additional information you want to store alongside the user should use a firestore. You should have a collecton for users, then each document should be named after the `User.uid` and contain the additional data you want to store.
|
|
|
|
## Update password/email
|
|
|
|
The instructions to update a password/email:
|
|
<https://firebase.google.com/docs/auth/web/manage-users#re-authenticate_a_user>
|
|
mention using `reauthenticateWithCredential`. This is only needed if using a 3rd party auth method which returns this credential object. If using native firebase logins then simply forcing the user to resign in is sufficient.
|
|
|
|
## Adding material icons to Vuetify project
|
|
|
|
`yarn add @mdi/font -D`
|
|
|
|
## Controlling layouts
|
|
|
|
### Spacing
|
|
|
|
<https://vuetifyjs.com/en/styles/spacing/>
|
|
|
|
You can use helper classes to apply custom margins/padding to elements.
|
|
|
|
You can apply padding to left: `class="pl-3"`.
|
|
Or apply margin to all: `class="ma-4"`.
|
|
|
|
You can use this to center objects without using flex:
|
|
`class="mx-auto"`.
|
|
|
|
### Display helpers
|
|
|
|
The display helpers allow you to control the dispaly of content. These can be used to hide/show elements based on the current viewport, or the actual display element type.
|
|
|
|
<https://vuetifyjs.com/en/styles/display/>
|
|
|
|
### Hide/Display elements for different widths
|
|
|
|
You can hide specific viewport sizes with:
|
|
<https://vuetifyjs.com/en/styles/display/#visibility>
|
|
|
|
`d-flex` by default without any size will apply to `xs` and above.
|
|
|
|
You can make things visible only on one viewport with:
|
|
`class="d-none d-lg-flex d-xl-none"`
|
|
|
|
You can make things hide only on one viewport with:
|
|
`class="d-lg-none d-xl-flex"`
|
|
|
|
You can hide multiple by using combinations of the above, or, use the following lateral display helper classes:
|
|
`class="hidden-md-and-up"` and `class="hidden-sm-and-down"`
|
|
|
|
### flex
|
|
|
|
Using flex will make the object fill the entire viewport, rather than adhering to the margins/widths by default. There is a lot more to flex - you can make things align left/right, vertical alignment and more:
|
|
<https://vuetifyjs.com/en/styles/flex/#flex>
|
|
|
|
### cols
|
|
|
|
In a `<v-row>` you can have many `<v-col>`. You can have as many of these and use the `cols` prop to control how wide the content should be.
|
|
|
|
```html
|
|
<v-col cols="4" class="appTitle d-flex justify-start">
|
|
<v-toolbar-title>
|
|
Savvy Firebase tutorial
|
|
</v-toolbar-title>
|
|
</v-col>
|
|
```
|
|
|
|
You can combine this with `d-flex` and justify to control the positioning and alignment:
|
|
|
|
<https://vuetifyjs.com/en/styles/flex/#flex-justify>
|
|
|
|
Justify classes include:
|
|
|
|
- `justify-start`
|
|
- `justify-end`
|
|
- `justify-center`
|
|
- `justify-space-between`
|
|
- `justify-space-around`
|
|
|
|
Using `cols`, `d-flex` and `justify` you can control precisely how things should be laid out for different screen sizes.
|
|
|
|
- Use `<v-col>`, use the prop `cols=""` to control how wide it should be.
|
|
- Use `<v-spacer>`, to dynamically fill space.
|
|
- Use `class="d-flex"` and the justify classes.
|
|
- Use `class="d-none d-xl-flex"` to control layouts for different sizes.
|
|
- Use `class="hidden-md-and-up"` to quickly control layouts for different sizes.
|
|
|
|
### Dual layouts
|
|
|
|
You can have the same html element for different sizes.
|
|
|
|
The layout you want for the screen you want to break on should **not** include it.
|
|
|
|
For example, to break on the medium viewport and have the second layout apply to it:
|
|
|
|
```html
|
|
<v-app-bar flat color="indigo" app class="hidden-md-and-up"></v-app-bar>
|
|
<v-app-bar flat color="indigo" app class="hidden-sm-and-down"></v-app-bar>
|
|
```
|
|
|
|
Here the second layout does not include the medium layout, hence the medium layout will apply to it.
|
|
|
|
## App bar
|
|
|
|
### Gradient as a background colour
|
|
|
|
The background image to the app bar is provided with a `src` prop.
|
|
|
|
If you want to apply a fade gradient colour on top of the image, you should use a scoped slot:
|
|
|
|
```html
|
|
<v-app-bar
|
|
flat
|
|
app
|
|
class="hidden-sm-and-down"
|
|
src="https://www.stellamccartney.com/cloud/smcwp/uploads/2016/01/1920x1080-black-solid-color-background.jpg"
|
|
>
|
|
<template v-slot:img="{props}">
|
|
<v-img
|
|
v-bind="props"
|
|
gradient="to top right, rgba(100,115,201,.7), rgba(25,32,72,.7)"
|
|
></v-img> </template
|
|
></v-app-bar>
|
|
```
|
|
|
|
If you want to just use a gradient (no img), then apply a solid colour image and then use a scoped slot with the gradient you want.
|
|
|
|
## Router
|
|
|
|
When linking to routes, you should use `<router-link>`:
|
|
|
|
```html
|
|
<router-link :to="{ name: 'Login' }">
|
|
<span class="mr-3">Sign In</span>
|
|
</router-link>
|
|
```
|
|
|
|
You can apply transitions on a route change:
|
|
|
|
```html
|
|
<transition name="slide">
|
|
<router-view></router-view>
|
|
</transition>
|
|
```
|
|
|
|
## vue-responsive-video-background-player
|
|
|
|
<https://github.com/avidofood/vue-responsive-video-background-player>
|
|
|
|
yarn add vue-responsive-video-background-player
|
|
|
|
ffmpeg -an -i Optical\ Fibers\ 1.mov -vcodec libx264 -pix_fmt yuv420p -profile:v baseline -level 3 optical.mp4
|
|
|
|
<https://cli.vuejs.org/guide/html-and-static-assets.html#disable-index-generation>
|
|
|
|
If using the public folder (not `./assets`) then follow these instructions:
|
|
<https://cli.vuejs.org/guide/html-and-static-assets.html#the-public-folder>
|
|
|
|
For videos in ./assets do the following:
|
|
|
|
```javascript
|
|
export default {
|
|
data() {
|
|
return {
|
|
video: require("../assets/videos/optical.mp4")
|
|
};
|
|
}
|
|
};
|
|
```
|
|
|
|
and reference it in the component:
|
|
|
|
```html
|
|
<video-background :src="video" style=" height: 100vh;"> </video-background>
|
|
```
|
|
|
|
This is done this way because webpack will apply custom names to the assets - this is so it can handle caching.
|
|
|
|
You can find full props to customise the video:
|
|
<https://github.com/avidofood/vue-responsive-video-background-player#props>
|
|
|
|
You can set a gradient to the image to improve visibility:
|
|
|
|
```javascript
|
|
style = " height: 100vh;";
|
|
overlay = "linear-gradient(45deg,#2a4ae430,#fb949e6b)";
|
|
```
|
|
|
|
## Dynamically hide app bar
|
|
|
|
Use the Vuex store to determine when you want to hide the app bar:
|
|
|
|
```javascript
|
|
state: {
|
|
fullScreen: false
|
|
},
|
|
getters: {
|
|
fullScreen: state => {
|
|
return state.fullScreen
|
|
}
|
|
},
|
|
mutations: {
|
|
fullScreen(state, fullScreen) {
|
|
state.fullScreen = fullScreen;
|
|
}
|
|
},
|
|
```
|
|
|
|
and create the lifecycle actions in the component that houses the appbar:
|
|
|
|
```javascript
|
|
created () {
|
|
this.$store.commit("fullScreen", true);
|
|
},
|
|
beforeDestroy () {
|
|
this.$store.commit("fullScreen", false);
|
|
},
|
|
```
|
|
|
|
Then you can wrap the appbar in a `v-if`:
|
|
|
|
```html
|
|
<v-app-bar
|
|
flat
|
|
app
|
|
class="hidden-sm-and-down"
|
|
color="#EEEEEE"
|
|
v-if="!this.$store.getters.fullScreen"
|
|
></v-app-bar>
|
|
```
|
|
|
|
## Change default font colour
|
|
|
|
In `_variables.scss` create a variable with the colour you want:
|
|
|
|
```scss
|
|
$mainColor: #323947;
|
|
```
|
|
|
|
Then create a new class `fontColor` to apply to the router, and edit the default `theme--light` class for Vuetify to apply this colour:
|
|
|
|
```scss
|
|
.theme--light.v-application,
|
|
.fontColor,
|
|
.theme--light.v-sheet {
|
|
color: $mainColor !important;
|
|
// color: red !important;
|
|
}
|
|
```
|
|
|
|
Then in `App.vue` apply the `fontColor` class to the `<v-app>`:
|
|
|
|
```html
|
|
<v-app
|
|
:style="{ background: $vuetify.theme.themes.light.background }"
|
|
class="fontColor"
|
|
></v-app>
|
|
```
|
|
|
|
## Grids
|
|
|
|
<https://vuetifyjs.com/en/components/grids/#row-and-column-breakpoints>
|
|
|
|
In addition to using the flex classes you can use the grid system. The grid system allows you to create rows and columns and use props to control how the content should be displayed.
|
|
|
|
This playground demonstrates what `align` and `justify` can do:
|
|
<https://vuetifyjs.com/en/components/grids/#playground>
|
|
|
|
The grid system applies to `<v-row>` and you can use the following props:
|
|
|
|
- `align` controls the y-axis. You have `start`, `center`, `end`, `baseline` and `stretch`.
|
|
- `justify` controls the x-axis. You have `start`, `center`, `end`, `space-around` and `space-between`.
|
|
|
|
For `<v-col>` only `align-self` is available. To align content on a column, or any other element like a card, you should use the same classes as in the flex system. For example:
|
|
|
|
```html
|
|
<v-col cols="5" align-self="start" class="d-flex justify-end pr-0"></v-col>
|
|
```
|
|
|
|
## Container filling whole page
|
|
|
|
A container should be used whenever you want to use `<v-col>` and `<v-row>`. To make this container fill the whole page (and be able to use `align` props and flex classes) you should specify the following two props:
|
|
|
|
- `fill-height`
|
|
- `fluid`.
|
|
|
|
To make content fill the width of the element it is in, you can use the following css:
|
|
|
|
```css
|
|
.full-width {
|
|
width: 100%;
|
|
}
|
|
```
|
|
|
|
`width` sets the element to the percentage of its parent. So to have a textbox fill the width of the v-card element it is in you should set the `<v-card>`, `<v-form>` and `<v-text-field>` to `width: 100%;`. As long as the parent elements have 100%, you can set the text input to be a percentage of this, say 50%.
|
|
|
|
## Multi column layouts
|
|
|
|
An example can be found here:
|
|
<https://git.panaetius.co.uk/web-development/savvy-firebase/src/branch/base-template/src/views/forms/LoginForm.vue>
|
|
|
|
You can make use of the above to create dynamic layouts.
|
|
|
|
One idea (for a login page) might be to use the following nested layout:
|
|
|
|
### Container
|
|
|
|
A `<v-container>` with `fill-height` and `fluid` props.
|
|
|
|
### Row
|
|
|
|
A `<v-row>`
|
|
|
|
### Columns
|
|
|
|
A `<v-col>` with `align-self="stretch"` and `class="d-flex flex-column justify-space-between"`.
|
|
|
|
`align-self=stretch` allows each child of the column to _stretch_ (<https://developer.mozilla.org/en-US/docs/Web/CSS/align-items)>.
|
|
|
|
`class="d-flex flex-column justify-space-between"` allows each child of the column to flex - with justify-space-between putting them equally apart top to bottom. It's used to equally space out the _rows_ inside this column. Even though we are not using `<v-row>`.
|
|
|
|
### Cards
|
|
|
|
A `<v-card>` with `class="d-flex align-end flex-column"`.
|
|
|
|
`class="d-flex align-end flex-column"` allows content inside the card to flex. The `align-end` means they will be on the right hand side and flex-column means they are flexing across columns.
|
|
|
|
To make text align right, you should use the `text-right` class:
|
|
|
|
`<p class="whiteText font-regular text-right mb-0">`
|
|
|
|
This is because although the `<p>` element will align to the right becasue of the class from the `<v-card>`, the text inside will align to the left.
|
|
|
|
We can add `color="rgb(0, 0, 0, 0)"` and `flat` props to the card - allowing it to seamlessly blend in with the background.
|
|
|
|
We can add mulitple cards to this layout in this column - and control how they are spaced with the props on the column.
|
|
|
|
We can add `<v-spacer>` and then add additional colums with the same props to add content in a column like manner.
|
|
|
|
Important!
|
|
|
|
If you want content to be aligned in a column with each item on a new line, then use:
|
|
|
|
```html
|
|
<v-col cols="6" align-self="center" class="">
|
|
<v-card color="rgb(0, 0, 0, 0)" flat class="d-flex align-center flex-column">
|
|
<v-icon color="white" size="3em">mdi-account-circle</v-icon>
|
|
<p class="mb-0 display-2">Login</p></v-card
|
|
></v-col
|
|
>
|
|
```
|
|
|
|
## Helper classes
|
|
|
|
### Spacing
|
|
|
|
<https://vuetifyjs.com/en/styles/spacing/>
|
|
|
|
You can use classes like `ma-2` and `pd-3` to control margin/padding in directions for any component.
|
|
|
|
See the playground for a quick demonstration on what each one does:
|
|
|
|
<https://vuetifyjs.com/en/styles/spacing/#playground>
|
|
|
|
## Typography
|
|
|
|
There are quite a few helper classes available to control font sizes and styles.
|
|
|
|
<https://vuetifyjs.com/en/styles/typography/>
|
|
|
|
There are two types of styles: Typography Display Classes and Style and Weight Classes.
|
|
|
|
Examples include `.display-2` and `.font-weight-black`.
|
|
|
|
### Replace Vuetify default font with custom
|
|
|
|
Fonts needed to replace the Roboto default:
|
|
|
|
- Thin
|
|
- Regular
|
|
- Medium
|
|
- Light
|
|
- Condensed Light (Light)
|
|
- Bold
|
|
- Black
|
|
- italic
|
|
- Light italic
|
|
- Medium italic
|
|
- Bold italic
|
|
|
|
If font styles dont exist then substitute them with the closest type.
|
|
|
|
An example of a stylesheet replacing all of these with the Gilroy font is here:
|
|
<https://git.panaetius.co.uk/web-development/savvy-firebase/src/branch/base-template/src/scss/_variables.scss>
|
|
|
|
## Custom colour theme
|
|
|
|
Creating a custom colour theme for Vuetify is straightforward.
|
|
|
|
<https://mycolor.space> is a good resource to generate palettes from a colour.
|
|
|
|
See <https://vuetifyjs.com/en/customization/theme/#customizing> for details on customising a theme.
|
|
|
|
### Editable colours
|
|
|
|
You change the `Vuetify` object in `vuetify.js`:
|
|
|
|
```javascript
|
|
export default new Vuetify({
|
|
icons: {
|
|
iconfont: "mdi"
|
|
},
|
|
theme: {
|
|
themes: {
|
|
light: {
|
|
primary: "#051937",
|
|
secondary: "#374366",
|
|
accent: "#d4a418",
|
|
background: "#e8e8e8"
|
|
}
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
These are the editable colours you can choose for Vuetify
|
|
|
|
```json
|
|
{
|
|
"primary": "#1976D2",
|
|
"secondary": "#424242",
|
|
"accent": "#82B1FF",
|
|
"error": "#FF5252",
|
|
"info": "#2196F3",
|
|
"success": "#4CAF50",
|
|
"warning": "#FFC107"
|
|
}
|
|
```
|
|
|
|
These follow the Material style of colours:
|
|
<https://material.io/design/color/the-color-system.html#color-theme-creation>
|
|
|
|
The accent colour in Vuetify isn't really specified in the Material colour design - typically the secondary colour would be used as an accent colour - with shades of the primary used throughout the UI. However in some themes you may wish to use primary and secondary together, and have a seperate accent colour.
|
|
|
|
<https://material.io/design/color/the-color-system.html#color-theme-creation>
|
|
|
|
### Colour variants
|
|
|
|
Vuetify will automatically generate darken and lighten colour variants of the primary and secondary colours in the theme. If you want to control these manually you can do so following the instructions:
|
|
<https://vuetifyjs.com/en/customization/theme/#custom-theme-variants>
|
|
|
|
The variants you can use are:
|
|
|
|
```json
|
|
{
|
|
"base": "string",
|
|
"lighten5": "string",
|
|
"lighten4": "string",
|
|
"lighten3": "string",
|
|
"lighten2": "string",
|
|
"lighten1": "string",
|
|
"darken1": "string",
|
|
"darken2": "string",
|
|
"darken3": "string",
|
|
"darken4": "string"
|
|
}
|
|
```
|
|
|
|
You can apply these as a class to the object you want to darken/lighten.
|
|
For example:
|
|
`<v-btn color="primary" class="darken-2">Hello</v-btn>`
|
|
|
|
## Forms
|
|
|
|
### Changing the colour of form inputs
|
|
|
|
You can change the background colour, and the highlight colour (when clicked) with the following props:
|
|
|
|
```html
|
|
<v-text-field
|
|
v-model="username"
|
|
background-color="rgb(100%, 100%, 100%, 10%)"
|
|
color="rgb(100%, 100%, 100%, 10%)"
|
|
class="white-placeholder"
|
|
></v-text-field>
|
|
```
|
|
|
|
To change the placeholder (text) colour you should use a custom class that overwrites this colour:
|
|
|
|
```css
|
|
.white-placeholder ::v-deep input::placeholder {
|
|
color: white !important;
|
|
opacity: 1;
|
|
}
|
|
```
|
|
|
|
To change the label (text) colour:
|
|
|
|
```css
|
|
.white-placeholder ::v-deep .v-label {
|
|
color: white !important;
|
|
opacity: 1;
|
|
}
|
|
```
|
|
|
|
To change the input colour (the text that is typed in by the user) we should use another custom class:
|
|
|
|
```css
|
|
.white-placeholder ::v-deep input {
|
|
color: white !important;
|
|
opacity: 1;
|
|
}
|
|
```
|
|
|
|
We have to use `::v-deep` because we are in a scoped component. Any nested css classes/variables in a scoped component will have a random id attached to them (vue does this dynamically). The `::v-deep` will make sure that the nested css gets the formatting applied. See <https://vue-loader.vuejs.org/guide/scoped-css.html#deep-selectors> for details.
|
|
|
|
## Overwriting sass/scss variables
|
|
|
|
<https://vuetifyjs.com/en/customization/sass-variables/>
|
|
|
|
Create a `_variables.scss` in `./src/scss`.
|
|
|
|
If Vuetify is installed through the Vuetify CLI then this `scss` file will be automatically bootstrapped into the App. If you want to write additional sheets then you should edit the `vue.config.js` file and add the following to `module.exports`:
|
|
|
|
```scss
|
|
module.exports = {
|
|
css: {
|
|
loaderOptions: {
|
|
scss: {
|
|
prependData: `
|
|
@import "@/scss/_variables.scss";
|
|
`
|
|
}
|
|
}
|
|
},
|
|
transpileDependencies: ["vuetify"]
|
|
};
|
|
```
|
|
|
|
Overwriting `sass` variables is easy. You need to simply define them in this `_variables.scss` file and they will be used in the main app.
|
|
|
|
You can find a list of default variables <https://vuetifyjs.com/en/customization/sass-variables/>.
|
|
|
|
Or you can use the variables defined in the `sass` section of the components api documentation.
|
|
|
|
## Slots
|
|
|
|
When using slots in Vuetify find the slot name from the api documentation.
|
|
|
|
To use a slot, you should create a `<template>` inside the component and pass a `v-slot:$NAME` directive.
|
|
|
|
For example:
|
|
`<template v-slot:prepend-inner>`
|
|
|
|
You can also use `#` as a keybinding for `v-slot`:
|
|
`<template #prepend-inner>`
|
|
|
|
An example of passing a prepend icon to a `<v-text-field>`:
|
|
|
|
```html
|
|
<template #prepend-inner>
|
|
<v-icon>
|
|
mdi-account-circle
|
|
</v-icon>
|
|
</template>
|
|
```
|
|
|
|
Expects the v-img component. Scoped props should be applied with
|
|
v-bind="props".
|