Uploading a file in Alfresco via JS API - javascript

I'm trying to upload a file from a node application to my local Alfresco.
I managed to login, create and delete folders but not files.
let AlfrescoApi = require('alfresco-js-api');
let alfrescoJsApi = new AlfrescoApi();
let fs = require('fs');
alfrescoJsApi.login('admin', 'admin').then(function (data) {
console.log('API called successfully login ticket:' + data);
var fileToUpload = fs.createReadStream('./testFile.txt');
fileToUpload.name= "testFile.txt"
alfrescoJsApi.upload.uploadFile(fileToUpload, 'Sites/test-site/documentLibrary')
.then(function () {
console.log('File Uploaded in the root');
}, function (error) {
console.log('Error during the upload' + error);
});
}, function (error) {
console.log("Error, cannot connect to Alfresco");
});
The previous code return the error :
Error during the uploadError: {"error":{"errorKey":"Required parameters are missing","statusCode":400,"briefSummary":"05010132 Required parameters are missing","stackTrace":"Pour des raisons de sécurité, le traçage de la pile n'est plus affiché, mais la propriété est conservée dans les versions précédente.","descriptionURL":"https://api-explorer.alfresco.com"}}
And I don't know what I am doing wrong, I tried every methods with differents parameters listed here : https://www.npmjs.com/package/alfresco-js-api#upload-file but always got the same error...
If anyone could help me it would be great, thanks =)
EDIT :
So I gave up this method, and start trying directly with rest requests, I managed to write this piece of code :
var http = require("http");
var options = {
'host': 'localhost',
'port': '8080',
'path': '/alfresco/service/api/upload?alf_ticket='+ticket,
'method': 'POST',
'Content-Type': 'application/json'
};
var fs = require('fs')
var fileToUpload = fs.createReadStream('./testFile.txt');
var body = {
"filedata": fileToUpload,
"filename": "testFile.txt",
"description": "none",
"siteid": "test-site",
"containerid": "documentLibrary"
}
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.write(JSON.stringify(body));
req.end();
But, now, I have an error 500 ...
STATUS: 500
HEADERS: {"server":"Apache-Coyote/1.1","cache-control":"no-cache","expires":"Thu, 01 Jan 1970 00:00:00 GMT","pragma":"no-cache","content-type":"application/json;charset=UTF-8","transfer-encoding":"chunked","date":"Thu, 01 Jun 2017 14:20:43 GMT","connection":"close"}
BODY: {
"status" :
{
"code" : 500,
"name" : "Internal Error",
"description" : "An error inside the HTTP server which prevented it from fulfilling the request."
},
"message" : "05010287 Unexpected error occurred during upload of new content.",
"exception" : "",
"callstack" :
[
],
"server" : "Community v5.2.0 (r135134-b14) schema 10 005",
"time" : "1 juin 2017 16:20:43"
}
I searched online, but I couldn't find any answers to this :/
Please if anyone have any idea ... thanks

Basically there are some issues with let fs = require('fs'); line.I just got it on below link.
https://github.com/angular/angular-cli/issues/5324
Below is the working example of file upload, using html file input element.I didn't override much thing.Basically on default alfresco angular component i just used home component and added your code in it and modified the required things like adding an html file upload element.
home.component.ts
import { Component } from '#angular/core';
import { AlfrescoApi } from 'alfresco-js-api';
#Component({
selector: 'home-view',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent {
public file: File;
changeListener(event) {
this.file = event.target.files[0];
}
uploadFileFromUI() {
let fs = require('fs');
let alfrescoApi = require('alfresco-js-api');
let alfrescoJsApi = new alfrescoApi();
let fileToUpload = this.file;
alfrescoJsApi.login('admin', 'admin').then(function (data) {
console.log('API called successfully login ticket:' + data);
alfrescoJsApi.upload.uploadFile(fileToUpload, 'Sites/test-site/documentLibrary')
.then(function () {
console.log('File Uploaded in the root');
}, function (error) {
console.log('Error during the upload' + error);
});
}, function (error) {
console.log('Error, cannot connect to Alfresco');
});
}
}
home.component.html
<!-- DOCUMENT LIST-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/files">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">dvr</i>
<span class="home--card__text">DocumentList - Content Services</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Demonstrates multiple Alfresco Content Services components used together to display the files of your Content Services instance:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
ng2-alfresco-core
</li>
<li>
<i class="material-icons home--feature-list__icon">dvr</i>
<span class="home--feature-list__text">Document List</span>
ng2-alfresco-documentlist
</li>
<li>
<i class="material-icons home--feature-list__icon">file_upload</i>
<span class="home--feature-list__text">Upload</span>
ng2-alfresco-upload
</li>
<li>
<i class="material-icons home--feature-list__icon">view_module</i>
<span class="home--feature-list__text">DataTable</span>
ng2-alfresco-datatable
</li>
</ul>
</div>
</div>
<!-- Process Services-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/activiti">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">apps</i>
<span class="home--card__text">Process Services</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Demonstrates multiple Alfresco Process Services components used together to show your Process Services process and tasks:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
ng2-alfresco-core
</li>
<li>
<i class="material-icons home--feature-list__icon">view_module</i>
<span class="home--feature-list__text">App List</span>
ng2-activiti-apps
</li>
<li>
<i class="material-icons home--feature-list__icon">view_headline</i>
<span class="home--feature-list__text">Task List</span>
ng2-activiti-tasklist
</li>
<li>
<i class="material-icons home--feature-list__icon">view_headline</i>
<span class="home--feature-list__text">Process List</span>
ng2-activiti-processlist
</li>
<li>
<i class="material-icons home--feature-list__icon">view_quilt</i>
<span class="home--feature-list__text">Form</span>
ng2-activiti-form
</li>
<li>
<i class="material-icons home--feature-list__icon">pie_chart</i>
<span class="home--feature-list__text">Analytics</span>
ng2-activiti-analytics,
ng2-activiti-diagrams
</li>
<li>
<i class="material-icons home--feature-list__icon">view_module</i>
<span class="home--feature-list__text">DataTable</span>
ng2-alfresco-datatable
</li>
</ul>
</div>
</div>
<!-- DATATABLE-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/datatable">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">view_module</i>
<span class="home--card__text">DataTable - Content Services & Process Services</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Basic table component:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
ng2-alfresco-core
</li>
</ul>
</div>
</div>
<!-- UPLOADER-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/uploader">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">file_upload</i>
<span class="home--card__text">Uploader - Content Services</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Basic table uploader component for the Content Services & Process Services:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
ng2-alfresco-core
</li>
</ul>
</div>
</div>
<!-- LOGIN-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/login">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">account_circle</i>
<span class="home--card__text">Login - Content Services & Process Services</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Login component for the Content Services and Process Services:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
ng2-alfresco-core
</li>
</ul>
</div>
</div>
<!-- WEBSCRIPT-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/webscript">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">extension</i>
<span class="home--card__text">Webscript - Content Services</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Displays and creates webscripts in your Content Services instance:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Communication with the Rest Api and core services</span>
ng2-alfresco-core
</li>
</ul>
</div>
</div>
<!-- TAG-->
<div class="demo-card-square mdl-card mdl-shadow--2dp home-cards">
<div class="mdl-card__title mdl-card--expand" routerLink="/tag">
<h2 class="mdl-card__title-text">
<i class="material-icons home--card__icon">local_offer</i>
<span class="home--card__text">Tag - Content Services</span>
</h2>
</div>
<div class="mdl-card__supporting-text">
Displays and adds tags to the node of your Content Services instance:
<ul class="home--feature-list">
<li>
<i class="material-icons home--feature-list__icon">brightness_1</i>
<span class="home--feature-list__text">Communication with Rest</span>
ng2-alfresco-core
</li>
</ul>
</div>
</div>
<br/>
<br/>
<br/>
<input type="file" (change)="changeListener($event)">
<button (click)='uploadFileFromUI()'>upload</button>

So, I figured out how to upload a file :
var fs = require('fs')
var request = require('request')
var r = request.post('http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/-root-/children?alf_ticket='+JSON.parse(chunk).data.ticket, function callback(err, httpResponse, body) {
if(err || JSON.parse(body).error) {
return console.log('Upload failed : ' + body)
}
console.log('Upload success')
})
var form = r.form()
form.append("name", "testFile.txt")
form.append("nodeType", "cm:content")
form.append("relativePath", "Sites/test-site/documentLibrary")
form.append("filedata",fs.createReadStream('./testFile.txt'))
Works fine to me =)

alfresco-js-api work fine but you made the wrong choice of module in your first code.
You had to choose alfresco-js-api-node instead of alfresco-js-api
Installer for browser versions:
npm install --save alfresco-js-api
Installer for node versions:
npm install --save alfresco-js-api-node
Import library for node projects
var AlfrescoApi = require('alfresco-js-api-node');

Related

I keep getting Uncaught TypeError: Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'

I'm trying to make my navbar sticky when it gets to a certain section of my website but my intersectionObserverApi isn't working. I think it has something to do with my useRefs being null when I try to select the section element I want to observe.I have tried selecting them using querySelector but didn't work either.
This is in React btw any help would be appreciated.
Here is my component:
import { React, useRef } from "react";
import "./About.css";
import Image from "../Images/7F1E6503-0880-4C1A-B2E8-070D0FAE543B.jpg";
const About = () => {
const aboutSectionRef = useRef("");
console.log(aboutSectionRef); // getting object with key value pair of current: ''
const el = aboutSectionRef.current;
console.log(el); // I'm getting null in the console.log
function stickyNavBar(entries, observer) {
console.log(entries);
}
document.addEventListener("DOMContentLoaded", function () {
const sectionObserver = new IntersectionObserver(stickyNavBar, {
root: null,
threshold: 0.1,
});
sectionObserver.observe(el);
});
// const aboutSectionRef = useRef(null);
// document.addEventListener(
// "DOMContentLoaded",
//
// );
return (
<section
ref={aboutSectionRef}
id="about-section"
className="about-section aboutsectionref"
>
<img className="headshot" src={Image} alt="pic of Osman" />
<h1>Nice to meet you</h1>
<p>
Over the past 2 years I have embarked on a journey that has undoubtedly
<span className="blue"> challenged</span> me like never before when I
decided to start
<span className="blue"> learning</span> how to code. I am a{" "}
<span className="blue"> self-taught</span> web developer with{" "}
<span className="blue"> passion</span> and{" "}
<span className="blue"> determination</span> for anything I set my mind
to.
</p>
<h2>Attributes I bring to the team</h2>
<div className="two-uls">
<ul>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Open-Minded
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Team Player
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Drive to
self-improve
</li>
</ul>
<ul>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Time Management
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Communication
</li>
<li>
<i className="fa-solid fa-circle-check fa-1x"></i> Attention to
detail
</li>
</ul>
</div>
</section>
);
};
export default About;

Getting highest score values from firebase database

In my website there are some films that i get from firebase. The scores of the movies are between 0 and 100. I already got all the movies in my website. I also want to display them in descending order.(for ex. top 5 rated movies) How can i achieve this? Thanks for your answers.
const app = initializeApp(firebaseConfig);
const db = getDatabase(app);
const auth = getAuth(app);
const firebaseRef= ref(getDatabase());
var body = document.getElementById('movies');
var body2 = document.getElementById('series');
function AddItemsToTable(name, score, img, id) {
var movies = `<div class="content"><img src="${img}" ><p>${name}</p> <p> <i class="fa fa-star checked" id="star${id}"></i> <a class="scoretxt">${score}%</a> </p> </div>`;
body.innerHTML+=movies;
}
function AddItemsToTable2(name, score, img, id) {
var series = `<div class="content"><img src="${img}" ><p>${name}</p> <p> <i class="fa fa-star checked" id="star2${id}"></i> <a class="scoretxt">${score}%</a> </p> </div>`;
body2.innerHTML += series;
}
//*******************************I got the movies************************************************
function AddAllItemsToTable(TheMovies){
var counter=0;
TheMovies.forEach(element => {
if (counter===6) {
return;
}
AddItemsToTable(element.movieName, element.movieScore, element.movieImage, element.movieId);
counter++;
});
}
//************************I got tv series*********************************************
function AddAllItemsToTable2(TheSeries){
var counter=0;
TheSeries.forEach(element => {
if (counter===6) {
return;
}
AddItemsToTable2(element.seriesName, element.seriesScore, element.seriesImage, element.seriesId);
counter++;
});
}
function AddAllItemsToTable3(TheMovies){
var counter=0;
TheMovies.forEach(element => {
if (counter===6) {
return;
}
AddItemsToTable3(element.movieName, element.movieScore, element.movieImage, element.movieId);
counter++;
});
}
function getAllDataOnce(){
const dbRef=ref(db);
get(child(dbRef,"Movies"))
.then((snapshot)=>{
var movies=[];
snapshot.forEach(childSnapshot => {
movies.push(childSnapshot.val())
});
AddAllItemsToTable(movies);
});
}
function getAllDataOnce2(){
const dbRef=ref(db);
get(child(dbRef,"Series"))
.then((snapshot)=>{
var series=[];
snapshot.forEach(childSnapshot => {
series.push(childSnapshot.val())
});
AddAllItemsToTable2(series);
});
}
window.onload = (event) => {
getAllDataOnce();
getAllDataOnce2();
};
<div class="grid-container">
<header class="header">
<div class="solheader">
<img src="img/sonlogo3.png" alt="logo">
<img src="img/logosmall.png" alt="logo" style="width:60px;height:48px;margin:5px;">
</div>
<div class="ortaheader">
<input type="text" placeholder="Movies or TV series.." class="searchbox"><i class="fa fa-search arama"></i> </input>
<ul>
<li class="categories">Categories <i class="fa fa-caret-down" style="font-size:16px;"> </i>
<ul class="dropdown">
<li>TV Series</li>
<li>Movies</li>
</ul>
</li>
</ul>
</div>
<div class="menu sagheader">
<ul>
<li>
<button class="ikon dropdown-toggle" type="button" data-toggle="dropdown"><i class="far fa-user"></i> </button>
<ul class="dropdown-menu">
<li class="accountname"><b><script>document.write(document.cookie.substring(5))</script></b></li>
<li class="login"><i class="fa fa-sign-in-alt" style="color:red;"></i> Login </li>
<li class="signup"><i class="fa fa-user-plus" style="color:red;"></i> Sign up </li>
<li class="logout"><a onclick="deletecookie()" style="cursor:pointer;"><i class="fas fa-door-open" style="color:red;"></i> Log out</a></li>
</ul>
</li>
</ul>
</div>
</header>
<div class="body" id="body">
<div class="baslik">Movies</div>
<div class="baslik2">See all</div>
<div id="movies">
</div>
<div class="baslik">Series</div>
<div class="baslik2">See all</div>
<div id="series">
</div>
<div class="baslik">Top Rated Movies</div>
<div class="baslik2">See all</div>
<div id="toprated">
</div>
</div>
<div class="footer">
<div class="">
<img src="img/sonlogo3.png" alt="logo">
<ul>
<li>Help</li>
<li>About</li>
<li>Contact</li>
<li>Terms and Policies</li>
</ul><br><br>
<ul>
<li>© 2021 Cinemeter</li>
<li class="destroy">|</li>
<li>All rights reserved.</li>
</ul>
</div>
</div>
</div>
Firebase Database
This is my website
While Firebase can order results, the results are always ascending. If you want to show them in descending order, you'll have to reverse them in your application code.
Something like this:
const query = query(child(dbRef,"Movies"), orderByChild("movieScore"));
get(query).then((snapshot)=>{
var movies=[];
snapshot.forEach(childSnapshot => {
movies.push(childSnapshot.val())
});
movies.reverse
});
If you want to get the top scores, you can use limitToLast in the query too:
const query = query(child(dbRef,"Movies"), orderByChild("movieScore"), limitToLast(5));
Also see the Firebase documentation on ordering and filtering data and limiting the number of results.
A few notes on your data structure:
Using sequential numeric keys for you nodes is an anti-pattern in Firebase, and it is typically better to use push keys. Also see Best Practices: Arrays in Firebase.
You're storing the score as a string, which is bound to lead to problems as strings are sorted lexicographically. I recommend converting your data to store the scores as numbers (so without " quotes around them).

Using background-image with ngStyle returns undefined

I try to add images (using API to load items) as background-image of element. But it keeps Cannot read property 'url' of undefined error. Though it actually renders url.
Here is the template side:
<div class="col s12 m4" *ngFor="let partner of partners">
<div class="card" *ngIf='partner'>
<div class="card-image " [ngStyle]="{'background-image': 'url(' + partner?.photo['url'] + ')'}">
<a class=" btn-floating halfway-fab waves-effect waves-light blue left ">
<i class="material-icons ">shopping_cart</i>
</a>
<a class="btn-floating halfway-fab red " [routerLink]='"/dashboard/partners/edit/"+partner["id"]'>
<i class="large material-icons ">mode_edit</i>
</a>
</div>
<div class="card-content ">
<h5 class="center font-weight-400 ">{{partner.name}}</h5>
<p class="center ">{{partner.category.name}}</p>
</div>
</div>
</div>
and controller:
export class PartnersListComponent implements OnInit {
partners: {}[] = [];
constructor(private _partnersService: PartnersService) {}
ngOnInit() {
this._partnersService.getPartners().subscribe(data => {
if (data.status == "200") {
this.partners = data.data;
}
});
}
}
Example data:
category:'',
created_at:"2017-12-27 12:57:50",
deleted_at:null,
first_entry:1,
id:1,
name:"Zara",
photo:{id: 5, url: "example.jpeg"},
updated_at:"2017-12-27 12:57:50",
username:"zara-001"
According to the error message, the photo field is not defined for at least one partner. You can protect against that situation with the elvis operator:
[ngStyle]="{'background-image': `url(${partner?.photo?.url})`}"
or
[style.background-image]="`url(${partner?.photo?.url})`"

Short HTML Code from Json will display the HTML code instead of the rendered version

I'm retrieving an array filled with user data. They should be displayed in a ul. One of the fields is the prefix for every user as an html code like this <span class="red-text">[Admin]</span>. But when I try to append the li element it renders the html code instead of the red version of the span.
My json code:
{
"users":[
{
"id":"1",
"usrname":"YannickFelix",
"email":"example#gmail.com",
"lvl":"4",
"prefix":"<span class=\"red-text\">[Admin]<\/span>"
}
]
}
And my javascript:
listElemTmplt = `
<li class="collection-item avatar">
<i class="material-icons circle {"{{color}}"}">person</i>
<span class="title">{"{{usrname}}"}</span>
<p>{"{{prefix}}"} {"{{usrname}}"} | {"{{email}}"}
</p>
<span class="secondary-content">
<a class="waves-effect waves-circle" href="users.php?action=edit&uID={"{{id}}"}">
<i class="material-icons grey-text text-darken-1">create</i>
</a>
<a class="waves-effect waves-circle waves-red modal-trigger" href="#modal{"{{id}}"}">
<i class="material-icons grey-text text-darken-1">delete</i>
</a>
</span>
<div id="modal{"{{id}}"}" class="modal">
<div class="modal-content black-text">
<h4>Löschen</h4>
<p>Möchtest Du den Benutzer "{"{{usrname}}"}" wirklich löschen?</p>
</div>
<div class="modal-footer">
Abbrechen
Löschen
</div>
</div>
</li>
`;
template = Handlebars.compile(listElemTmplt);
finishedString = [];
$.getJSON("**url**", function (data) {
console.log(data);
$("ul#users").html("");
data["users"].forEach(function (element, index, array) {
html = template({"{"}id: element["id"], usrname: element["usrname"], email: element["email"], prefix: element["prefix"]{"}"});
$("ul#users").append(html);
});
});
The example item in the List. [Admin] should be red and without the html code
Handlebars escapes the values you give to it when using {{prefix}}. When you want to use raw HTML you have to use {{{prefix}}} to tell it not to escape it.

Why is this template now showing up?

I have a problem with showing a template on my Meteor.js app. It's website_list. For some reason it doesn't show, maybe you can help me out?
I'm trying to show the website list from the websites MongoDB collection.
HTML Code:
<!-- master layout template -->
<template name="ApplicationLayout">
{{> yield "navbar"}}
{{> yield "main"}}
</template>
<!-- / master layout template -->
<!-- WELCOME -->
<template name="welcome">
<div class="container">
<div class="jumbotron">
<h1>Welcome to Site Ace, {{username}}!</h1>
Enter
</div>
</div>
</template>
<!-- / WELCOME-->
<!-- NAVBAR - you will be putting the login functions here -->
<template name="navbar">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">
Site Ace
</a>
</div>
<ul class="nav navbar-nav login">
<li>
{{> loginButtons}}
</li>
</ul>
</div>
</nav>
</template>
<template name="websites">
<div class="container">
{{> website_form}}
{{> website_list}}
</div>
</template>
<!-- / NAVBAR -->
<!-- WEBSITE FORM -->
<template name="website_form">
{{#if currentUser}}
<a class="btn btn-default js-toggle-website-form" href="#">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add a Website
</a>
{{/if}}
<div id="website_form" class="hidden_div">
<form class="js-save-website-form">
<div class="form-group">
<label for="url">Site address</label>
<input type="text" class="form-control" id="url" placeholder="http://blablabla.org">
</div>
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" placeholder="Mysite">
</div>
<div class="form-group">
<label for="description">Description</label>
<input type="text" class="form-control" id="description" placeholder="I found this site really useful for ...">
</div>
<button type="submit" class="btn btn-default js-">Submit</button>
</form>
</div>
</template>
<!-- / WEBSITE FORM -->
<!-- WEBSITE LIST -->
<template name="website_list">
<ol>
{{#each websites}}
{{>website_item}}
{{/each}}
</ol>
</template>
<!-- / WEBSITE LIST -->
<!-- WEBSITE ITEM -->
<template name="website_item">
<li>
{{title}}
<p>
{{description}}
</p>
<p>
<a href="/details/{{_id}}" class="btn btn-info">
Details
</a>
<a href="#" class="btn btn-success js-upvote">
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
</a>
<a href="#" class="btn btn-danger js-downvote">
<span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>
</a>
</p>
<!-- you will be putting your up and down vote buttons in here! -->
</li>
</template>
<!-- / WEBSITE ITEM -->
JS Code:
// SECURITY
Websites = new Mongo.Collection("websites");
// set up security on Websites collection
Websites.allow({
// we need to be able to update websites for ratings.
update:function(userId, doc){
console.log("Testing security on website update");
if (Meteor.user()){// they are logged in
return true;
} else {// user not logged in - do not let them update (rate) the website
return false;
}
},
insert:function(userId, doc){
console.log("Testing security on website insert");
if (Meteor.user()){ // they are logged in
if (userId != doc.createdBy){ // the user is messing around
return false;
}
else{ // the user is logged in, the website has the correct user id
return true;
}
}
else{ // user not logged in
return false;
}
},
remove:function(userId, doc){
return true;
}
})
// / SECURITY
if (Meteor.isClient) {
/////
// ROUTERS
/////
// GLOBAL LAYOUT
Router.configure({
layoutTemplate: 'ApplicationLayout'
});
// ROUTES
Router.route('/', function() {
this.render('welcome', { // welcome is the template to render
to:"main" // main is the template to render welcome INTO
});
});
Router.route('/websites', function() {
this.render('navbar', {
to:"navbar"
});
this.render('websites', {
to:"main"
});
});
Router.route('/websites/:_id', function () {
this.render('navbar', {
to:"navbar"
});
this.render('image', {
to:"main",
data:function(){
return Websites.findOne({_id:this.params._id});
}
});
});
/////
// STARTUP (Creating Websites)
/////
if (Meteor.isServer) {
// start up function that creates entries in the Websites databases.
Meteor.startup(function () {
// code to run on server at startup
if (!Websites.findOne()){
console.log("No websites yet. Creating starter data.");
Websites.insert({
title:"Goldsmiths Computing Department",
url:"http://www.gold.ac.uk/computing/",
description:"This is where this course was developed.",
createdOn:new Date()
});
Websites.insert({
title:"University of London",
url:"http://www.londoninternational.ac.uk/courses/undergraduate/goldsmiths/bsc-creative-computing-bsc-diploma-work-entry-route",
description:"University of London International Programme.",
createdOn:new Date()
});
Websites.insert({
title:"Coursera",
url:"http://www.coursera.org",
description:"Universal access to the world’s best education.",
createdOn:new Date()
});
Websites.insert({
title:"Google",
url:"http://www.google.com",
description:"Popular search engine.",
createdOn:new Date()
});
}
});
}
You forgot to implement a helper function for your website_list template, which returns documents of your Websites collection.
For example:
Template.website_list.helpers({
websites: function() {
return Websites.find();
}
});
Here's a MeteorPad.

Categories