Skip to content

Instantly share code, notes, and snippets.

@evalphobia
Created March 9, 2020 17:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evalphobia/f24a318973bda5a28c1755171a5bb89e to your computer and use it in GitHub Desktop.
Save evalphobia/f24a318973bda5a28c1755171a5bb89e to your computer and use it in GitHub Desktop.
(() => {
// initialize app
function init() {
_firebaseInit()
_firebaseAuthInit()
}
function _(el) {
return document.getElementById(el);
}
// initialize firebase
function _firebaseInit() {
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "<your own data here>",
authDomain: "<your own data here>",
databaseURL: "<your own data here>",
projectId: "<your own data here>",
storageBucket: "<your own data here>",
messagingSenderId: "<your own data here>",
appId: "<your own data here>"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
}
// initialize firebase auth via firebase-ui
function _firebaseAuthInit() {
var ui = new firebaseui.auth.AuthUI(firebase.auth());
var uiConfig = {
callbacks: {
signInSuccessWithAuthResult: function(authResult, redirectUrl) {
_('did-login').style.display = 'block';
_('non-login').style.display = 'none';
fetchFileListAndUpdateListView()
return false;
},
uiShown: function() {
_('loader').style.display = 'none';
}
},
signInFlow: 'popup',
signInOptions: [
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
],
};
ui.start('#firebaseui-auth-container', uiConfig);
}
//========================
// read data from Storage
//========================
const storagePrefix = 'uploaded_items/'
function fetchFileListAndUpdateListView() {
const listRef = firebase.storage().ref(storagePrefix);
let results = [];
listRef.listAll().then(res => {
res.items.forEach(itemRef => {
const path = itemRef.fullPath.replace(storagePrefix, '')
results.push(path)
});
updateListView(results)
}).catch(err => {
console.warn(`error on list: ${err}`)
});
}
function updateListView(list) {
// remove all list
const el = _("uploaded-data-list")
el.textContent = null;
while (el.firstChild) el.removeChild(el.firstChild);
// create new list
let fragment = document.createDocumentFragment();
list.forEach(item => {
// naming convention must be `{date}__{username}__{filename}`
// (e.g.) `2020-03-05__evalphobia__my_awesome_movie-01.mp4`
const parts = item.split('__')
const date = parts[0]
const user = parts[1]
const path = parts[2]
const td1 = document.createElement('td');
td1.appendChild(document.createTextNode(date))
const td2 = document.createElement('td');
td2.appendChild(document.createTextNode(user))
const td3 = document.createElement('td');
td3.appendChild(document.createTextNode(path))
const tr = document.createElement('tr');
tr.appendChild(td1)
tr.appendChild(td2)
tr.appendChild(td3)
fragment.appendChild(tr);
})
// add the list
el.appendChild(fragment)
}
//========================
// write data to Storage
//========================
const input = _('fileinput');
input.addEventListener("change", ev => {
const f = ev.target.files;
if (!f || f.length != 1) {
return
}
uploadFile(f)
})
function uploadFile(files) {
const file = files[0]
const fileName = getFileName(file)
displayFileName(fileName)
const storageRef = firebase.storage().ref(storagePrefix);
const uploadRef = storageRef.child(fileName);
const blob = new Blob(files, { type: file.type });
const uploadTask = uploadRef.put(blob) // file is uploading here!
uploadTask.on('state_changed', snapshot => {
// uploading...
const percent = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
_("progressBar").value = Math.round(percent);
_("progressStatus").innerHTML = Math.round(percent) + "% uploaded...";
}, err => {
// error occors when uploading...
alert("Failed to upload the file")
completeProgress()
}, () => {
// After the upload task...
alert("Upload Complete!")
completeProgress()
})
}
function getFileName(file) {
// get user name
const user = firebase.auth().currentUser;
let userName = user.email.split('@')[0];
if (!userName) {
// Don't allow empty email address user.
alert("Upload failed...")
location.reload()
return
}
// if the file name already contains double underscore, change to single.
const baseName = file.name.replace('__', '_')
userName = 'evalphovia'
const fileName = `${_getYYYYMMDD(new Date())}__${userName}__${baseName}`
return fileName
}
function _getYYYYMMDD(dt) {
const yyyy = dt.getFullYear();
const mm = ("00" + (dt.getMonth()+1)).slice(-2);
const dd = ("00" + dt.getDate()).slice(-2);
return `${yyyy}-${mm}-${dd}`
}
// clear input form and reload uploaded file list
function completeProgress() {
_("fileinput").disabled = '';
_("fileinput").value = '';
_("progressBar").value = 0;
_("progressStatus").innerHTML = ''
fetchFileListAndUpdateListView()
clearFileName()
}
// update display and refuse file upload
function displayFileName(name) {
const el = _("filename")
el.value = name
el.style.display = 'inline-block';
_("fileinput").disabled = true;
}
// clear display and accept file upload
function clearFileName(name) {
const el = _("filename")
el.value = ''
el.style.display = 'none';
_("fileinput").disabled = '';
}
init()
})();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome</title>
<!-- update the version number as needed -->
<script defer src="/__/firebase/7.9.3/firebase-app.js"></script>
<!-- include only the Firebase features as you need -->
<script defer src="/__/firebase/7.9.3/firebase-auth.js"></script>
<script defer src="/__/firebase/7.9.3/firebase-storage.js"></script>
<script src="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.js"></script>
<!-- <script src="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth__{lang}.js"></script> -->
<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.css" />
<!-- initialize the SDK after all desired features are loaded -->
<script src="https://www.gstatic.com/firebasejs/7.9.3/firebase.js"></script>
<script defer src="/__/firebase/init.js"></script>
</head>
<body>
<!-- #01 -->
<section id="non-login" class="container"">
<h2>Please login, then you can upload file. </h2>
<br />
<div id="loader">Firebase SDK Loading&hellip;</div>
<div id="firebaseui-auth-container"></div>
</section>
<!-- #02 -->
<section id="did-login" class="container" style="display: none;">
<div id="upload-form" class="upload-form">
<div class="upload-button">
Choose file
<input type="file" name="fileinput" id="fileinput" />
<input type="text" id="filename" class="filename" disabled />
</div>
<br />
<progress id="progressBar" class="progressbar" value="0" max="100"></progress>
<p id="progressStatus" class="progress-status"></p>
</div>
<hr />
<div id="uploaded-data">
<h3>Uploaded File List</h2>
<table class="list-table">
<thead>
<tr>
<th>Date</th>
<th>User</th>
<th>File</th>
</th>
</thead>
<tbody id="uploaded-data-list"></tbody>
</table>
<ul class="file-list">
</ul>
</div>
</section>
<script src="app.js"></script>
<style media="screen">
body {
background: #ECEFF1;
min-height: 100vh;
color: rgba(0,0,0,0.87);
margin: 0;
padding: 0;
}
.container {
background: white; max-width: 380px; margin: 100px auto 16px; padding: 32px 24px; border-radius: 3px;
}
.container h2 {
color: #333333;
font-weight: bold;
font-size: 16px;
margin: 0 0 8px;
}
.upload-form {
text-align: center;
}
.progressbar {
width: 150px;
}
.progress-status {
margin-top: 0px;
}
.upload-button {
display: inline-block;
position: relative;
overflow: hidden;
border-radius: 3px;
background: #3388cc;
color: #ffffff;
text-align: center;
padding: 10px;
line-height: 30px;
width: 180px;
cursor: pointer;
}
.upload-button:hover {
background: #4499dd;
}
.upload-button input[type=file] {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: pointer;
opacity: 0;
}
.filename {
display: none;
background: rgba(255,255,255,0.2);
border-radius: 3px;
padding: 3px;
color: #ffffff;
}
.list-table {
border: #ECEFF1 solid 1px;
border-collapse: collapse;
border-spacing: 8px 2px;
}
.list-table tbody {
border-top: #ECEFF1 solid 1px;
}
.list-table th, td {
padding: 2px;
border-left: #ECEFF1 solid 1px;
border-right: #ECEFF1 solid 1px;
}
</style>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment