Cloud Storage for Firebase: download metadata of all files - firebase-storage

Question: Is there a way to download the metadata of all the files in Cloud Storage?
Reference: I've taken a look at the documentation for AngularFire2 and while I can do a download of the metadata for one file I can't figure out how to pull the metadata for all the files in the storage.
AngularFire2 FireStorage documentation
Code: I'm pulling down the metadata for one file successfully.
Component.TS
fileUrl: Observable<string>;
fileCollection: Observable<any>;
constructor(firestorage: AngularFireStorage) {
const ref = firestorage.ref('nforms/').child('file.pdf');
this.fileUrl = ref.getDownloadURL();
this.fileCollection = ref.getMetadata();
}
Component.HTML
<tr *ngIf="fileCollection | async; let f">
<td><pre><code>{{f | json}}</code></pre> .
</td>
<td>f</td>
<div *ngIf="fileUrl | async; let url">
<td><a target="_self" [href]="url">download</a></td>
</div>
</tr>
Current Results
{
"type": "file",
"bucket": "this-is-a-secret",
"generation": "this-is-a-secret",
"metageneration": "1",
"fullPath": "nforms/file.pdf",
"name": "file.pdf",
"size": 318522,
"timeCreated": "2019-08-09T21:52:53.692Z",
"updated": "2019-08-09T21:52:53.692Z",
"md5Hash": "this-is-a-secret",
"contentDisposition": "inline; filename*=utf-8''file.pdf",
"contentEncoding": "identity",
"contentType": "application/pdf"
}

You will have to list all the files, then access their metadata individually. There aren't any bulk operations on object metadata.

Related

How can we create a Azure Pipeline(yaml approach) using Azure Devops rest api

How can we create a Azure Pipeline(yaml approach) using Azure Devops rest apis.
Basically I am trying to create a new pipeline programmatically and not through Azure Devops portal
I referred to this link below:
https://learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/pipelines/create?view=azure-devops-rest-6.0
but this does not provide the exact json body format required to create and configure a new pipline pointing to code repo. Kindly help me here
You can first use the Pipelines - Get rest api to check the definition json of the pipeline, and change the fields accordingly.
You can define the request body json as below, when calling Pipelines - Create rest api:
$body = #{
configuration=#{
variables=#{
customVariable=#{
value="value"
}
};
path="azure-pipelines.yml";
repository=#{
id= "repository-id";
name="repository-name"
type= "azureReposGit"
};
type= "yaml"
};
name= "pipeline-name";
folder= "\\"
}
The variables field define the pipeline Variables in the UI Page:
The path field points to pipeline yaml file in the code repo.
The repository field defines the code repo this pipeline targets to.
The folder field defines which folder the pipeline is placed:
If you use Build Definitions - Create rest api to create the yaml pipeline. You can check below request body json example:
$body='{ "variables": {
"customVariable": {
"value": "customValue",
"allowOverride": true
}
},
"process": {
"yamlFilename": "azure-pipelines.yml",
"type": 2
},
"repository": {
"id": "repo-id",
"type": "TfsGit",
"name": "repo-Nanme",
"defaultBranch": "refs/heads/master",
"clean": null,
"checkoutSubmodules": false
},
"name": "pipeline-name",
"path": "\\",
"type": "build",
"queueStatus": "enabled",
"project": {
"id": "project-id",
"name": "project-name"
}
}'
Update:
If you code repo is Githbub. You will have to create a github service connection in your azure devops project. And then pass the connection id in your api resquest body.
$body = #{
configuration=#{
variables=#{
customVariable=#{
value="value"
}
};
path="azure-pipelines.yml";
repository=#{
FullName="githubAccount/repoName";
type= "gitHub";
Connection= #{
id= "github service connection id"
}
};
type= "yaml"
};
name= "pipeline-name";
folder= "\\"
}
You can get the service connection id in the address bar. See below:

Adding document in Couchbase and missing JSON body

I am trying to use Couchbase REST API to add a document to the existing documents. I am just testing this in Postman while writing on the code.
POST:
http://<ip>:8091/pools/default/buckets/<bucketname>/docs/testdoc1?rev=1
Headers:
Accept: application/json
Authorization : xxxxx
Body:
Raw JSON (application/json)
{
"Name": "xxx",
"Address": "yyy",
"Phone number": "xxxx",
"Badge": "yyy",
"BadgeType": "xxx"
}
When I send above in Postman, It is adding this new doc. under couchbase documents/bucket, but on the body field it shows like, "Binary Document, base64 not available"
I tried even from my html code, but json body didn't receive at couchbase end.
<!DOCTYPE html>
<html>
<body>
<input type="submit" value="Start" onclick="submit()">
<script type="text/javascript">
var params = {
"Name": "xxx",
"Address": "yyy",
"Phone number": "xxxx",
"Badge": "yyy",
"BadgeType": "xxx"
}
function submit() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
alert(xhr.response);
}
}
xhr.open('post', 'http://<ip>:8091/pools/default/buckets/<buckname>/docs/testdochtml?rev=1', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Authorization', 'Basic ' + 'xxxxxxx');
xhr.send(JSON.stringify(params));
}
</script>
<p>Click on the submit button.</p>
</body>
</html>
Can someone guide me why is that JSON not going to couchbase in a correct way?
First off: as far as I know, this endpoint is not supported and it is not documented. If you see somewhere that it is supported, let me know, because I think that needs corrected. You should use one of the SDKs (Java, .NET, Node, etc) instead.
That being said, I was able to get it working via Postman. You can't just send raw JSON as the document. You need to POST encoded form data. One of the values this endpoint expects is "value", which contains the encoded JSON document.
Here's an example of what I did (I called my bucket "so"):
POST /pools/default/buckets/so/docs/testdoc2 HTTP/1.1
Host: localhost
cache-control: no-cache
Postman-Token: ba87ef4e-4bba-42b4-84da-ae775b26dbcb
value=%7B%0A%09%22Name%22%3A+%22xxx%22%2C%0A%09%22Address%22%3A+%22yyy%22%2C%0A%09%22Phone+number%22%3A+%22xxxx%22%2C%0A%09%22Badge%22%3A+%22yyy%22%2C%0A%09%22BadgeType%22%3A+%22xxx%22%0A%7D%0A
Note that value above is just the URL-encoded JSON from your question (Postman encoded it for me, and Postman must have added the cache-control header on its own too, because I did not specify that):

Unable to verify JobPosting in SDTT

Get frustrated with Schema.org’s JobPosting. I found Google Structured Data Testing Tool said:
100000 (The attribute baseSalary.itemtype has an invalid value.)
I have tried using this inside or outside of JobPosting as follows:
"#type":"MonetaryAmount",
"EmployeeRole":{
"baseSalary": "100000"
}
However, I found more than one problem.
<script type="application/ld+json">{
"#context": "http://schema.org",
"#type": "JobPosting",
"baseSalary":"100000",
"datePosted":"2017-06-18T15:14:57+00:00",
"validThrough":"2017-12-31T00:00:00+00:00",
"title":"Sales And Marketing Manager",
"description":"Responsible for Corporate and Travel Agent Room Sales for the hotel",
"educationRequirements":"S-1 Management",//educationRequirements
"employmentType":"Kontrak 1 Tahun",//employmentType
"experienceRequirements":"100 Tahun",//experienceRequirements
"industry":"Perpajakan Daerah Sumedang",//industry
"qualifications":"Single, Fresh Graduates dan suka ternak bebek",//qualifications
"responsibilities":"Tukang mbersihin kadang embek",//responsibilities
"skills":"Bisa menjahit, ngetik 40 jari",//skills
"workHours":"Jam 10 s/d 70",//workHours
"hiringOrganization":{
"#type":"Organization",
"name":"Equity Jimbaran Resort And Villa",
"sameAs":"http://equityhoteljimbaran.com",
"url":"http://equityhoteljimbaran.com"
},
"jobLocation":{
"#type":"Place",
"address":{
"#type":"PostalAddress",
"addressRegion":"Bali",
"addressCountry":"ID",
"streetAddress":"Jl.Muara 3, KM.18, Blok4, RT04/05, Tanjung Perak",//streetAddress
"addressLocality":"Jimbaran",//addressLocality
"postalCode":"56161"//postalCode
}
}
}
}
</script>
After long distance, finally, I find the solution:
<script type="application/ld+json">{
"#context": "http://schema.org",
"#type": "JobPosting",
"baseSalary":{
"#type":"MonetaryAmount",
"value":"100000",
"currency":"USD"
},
"datePosted":"2017-06-18T15:14:57+00:00",
"validThrough":"2017-12-31T00:00:00+00:00",
"title":"Sales And Marketing Manager",
"description":"Responsible for Corporate and Travel Agent Room Sales for the hotel",
"educationRequirements":"S-1 Management",//educationRequirements
"employmentType":"Kontrak 1 Tahun",//employmentType
"experienceRequirements":"100 Tahun",//experienceRequirements
"industry":"Perpajakan Daerah Sumedang",//industry
"qualifications":"Single, Fresh Graduates dan suka ternak bebek",//qualifications
"responsibilities":"Tukang mbersihin kadang embek",//responsibilities
"skills":"Bisa menjahit, ngetik 40 jari",//skills
"workHours":"Jam 10 s/d 70",//workHours
"hiringOrganization":{
"#type":"Organization",
"name":"Equity Jimbaran Resort And Villa",
"sameAs":"http://equityhoteljimbaran.com",
"url":"http://equityhoteljimbaran.com"
},
"jobLocation":{
"#type":"Place",
"address":{
"#type":"PostalAddress",
"addressRegion":"Bali",
"addressCountry":"ID",
"streetAddress":"Jl.Muara 3, KM.18, Blok4, RT04/05, Tanjung Perak",//streetAddress
"addressLocality":"Jimbaran",//addressLocality
"postalCode":"56161"//postalCode
}
}
}
}
</script>
From the structure data above,baseSalary expects type of MonetaryAmount, where the value is the amount of the salary, as follow:
"baseSalary":{
"#type":"MonetaryAmount",
"value":"100000",
},
However, when the baseSalary has been added and verified, Google, again, gave me error in currency which I placed it inside baseSalary:
"baseSalary":{
"#type":"MonetaryAmount",
"value":"100000",
"currency":"USD"
},
Done successfully.
This is an answer to #huykon225 question about microdata above, because I can't find that this question is answered in microdata context anywhere although the internet is full of corrected versions of json. Frustrated me, just took an hour or more to sort it...
Replace this in the original code:
<span itemprop="salaryCurrency">USD</span> <span itemprop="baseSalary">100000</span>
With this:
<div itemprop="baseSalary" itemscope="" itemtype="https://schema.org/MonetaryAmount">
<span itemprop="currency">USD</span>
<span itemprop="value">100000</span>
</div>

Flexible content modules in Silverstripe

We are looking at using Silverstripe CMS and want to be able to have modules which can be reordered.
We have come from a Wordpress setup and mostly use the flexible content ACF field. Modules (e.g. text, masthead or video) need to be able to be re-ordered.
We use our CMS's as an API so these modules are output as a section to the page or post:
[
{
"id": 10,
"title": "Post title",
"slug": "post_slug",
"path": "/post_slug",
"template": "campaign",
"published": "2017-05-25 06:09:36",
"image": null,
"seo": {
"title": "",
"description": "",
"image": {
},
},
"sections": [
{
"type": "masthead",
"Title": "",
"video": false,
"image": [
],
"showCta": false,
"cta": [
]
},
{
"type": "video_text",
"video_text": [
{
"type": "video",
"video_url": "https://www.youtube.com/watch?v=asdfa",
"video_length": "07:38",
"video_preview": false
},
{
"type": "text",
"title": "Video Title",
"content": "Video text content",
"call_to_action": false,
"cta": [
]
}
]
},
{
"type": "text",
"title": "Text Title",
"content": "",
"alignment": "centre",
"call_to_action": false,
"cta": {
"text": "CTA button",
"link_type": "internal_link",
"internal_link": "about",
"external_link": "",
"section_id": [
]
}
},
]
}
]
Does Silverstripe have it's own way of handling modules / do I need to ditch this flexible content modules method? How do others handle flexible content modules in Silverstripe?
Both silverstripe-blocks and silverstripe-elemental works very well in their own regard but I don't think they will achieve what you want. These modules don't really give you the power to use pre-defined templates. You can hook the templates in but the code will be massive. I not sure if there is an open source module for that yet.
From your JSON code, in order to have those Sections to render something like this below;
<section id="Sections">
<div id="video_text" class="section">
<iframe width="560" height="315" src="https://www.youtube.com/watch?v=asdfa" frameborder="0" allowfullscreen></iframe>
</section>
<div id="text" class="section">
<h2>Text Title</h2>
<a class='text-center btn btn-default' href="/about/">CTA button</a>
</section>
</sections>
You might want to do this.
Use DataObjects (DO) for you Sections, easy for re-ordering.
Create an abstract DO, BlockSection, with fields like Title(Varchar), Content(HTMLText), Sort(Int) and most importantly has_one to Page.
For the video use can name the DO VideoBlockSection and it extends BlockSection,
TextBlockSection for the other one. Don't forget the $singular_name for each DO (useful for nice class naming in the Grid)
On Page getCMSFields add the Grid to manage the Sections. You need to add GridFieldSortableRows and GridFieldAddNewMultiClass and now you can add you Section on each Page.
Add has_many from Page to BlockSection and a method that will render the Blocks and outputs the html.
Page.php
private static $has_many = array(
"Sections" => "BlockSection",
);
function SectionContent()
$aContent = ArrayList::create();
$oSections = $this->Sections();
if (count($oSections )) {
foreach ( $oSections as $oSection ) {
$aContent->push(ArrayData::create([
"Section" => $oSection,
"Content" => $oSection->renderWith([$oSection->ClassName, get_parent_class($oSection)]),
]));
}
}
return $aContent;
For the VideoBlockSection the template array list will be VideoBlockSection and BlockSection
VideoBlockSection.ss
<div id="video_text_{$ID}" class="section">
<iframe width="560" height="315" src="{$URL}" frameborder="0" allowfullscreen></iframe>
</section>
In you specific case, because you are using an API you need to use a wrapper to render the Template.
It needs to match [section][type] to a Template (renderWith) video_text to VideoBlockSection
Lastly in Page.ss
<% loop $SectionContent %>
{$Content}
<% end_loop %>
This was a proof of concept but its working for me so refactoring, speed and memory usage was not considered (but its working).
This way I had to ditch the unnecessary so called "page types" which I find not to be reusable in most cases.
This works 100% for me and I use it together with Bootstrap 3. I use it to create CTAs, parallax scroll, Google Map Section (multiple maps on one page), Thumbnails. Specify image resize method (Cropped, ByWidth, ByHeight).
DO NOT ditch that flexible content modules method.
I am working on an open source module which works with SS4 and Bootstrap 4 (with possibilities of using any other html framework)

Google Charts, Load Different Charts on One Page

I am trying to load a number of google charts on one page, however I am falling over trying to add the second.
I am testing the new Google Analytics SuperProxy feature, so the Data is being drawn in from a dataSourceURL
My code is below, as is the code works, however as soon as I uncomment out the section everything fails to load and for the life of me I cannot figure out how to fix this.
Hope someone can help.
<html>
<head>
<title>jmit</title>
<script type="text/javascript"
src='https://www.google.com/jsapi?autoload={"modules":[{"name":"visualization","version":"1","packages":["corechart","geochart"]}]}'>
</script>
<script type="text/javascript">
google.setOnLoadCallback(drawCharts);
function drawCharts(){
/*var data1 = new google.visualization.ChartWrapper({
"containerId":"Chart1_div",
"dataSourceUrl":"https://alexandalexaanalytics.appspot.com/query?id=ahdzfmFsZXhhbmRhbGV4YWFuYWx5dGljc3IVCxIIQXBpUXVlcnkYgICAgIDwiwoM&format=data-table-response",
"refreshInterval":3600,
"chartType":"GeoChart",
"options":{
"width": 630,
"height": 440,
"title": "test"
}
});
data1.draw();
}
*/
var data2 = new google.visualization.ChartWrapper({
"containerId":"Chart2_div",
"dataSourceUrl":"https://alexandalexaanalytics.appspot.com/query?id=ahdzfmFsZXhhbmRhbGV4YWFuYWx5dGljc3IVCxIIQXBpUXVlcnkYgICAgIDwiwoM&format=data-table-response",
"refreshInterval":3600,
"chartType":"ColumnChart",
"options":{
"width": 630,
"height": 440,
"title": "test"
}
});
data2.draw();
}
</script>
</head>
<body>
<h1>Test</h1>
<div id="Chart1_div"></div>
<p></p>
<div id="Chart2_div"></div>
</body>
</html>
You have an extra "}" after the data1.draw(); line, which is closing the drawCharts function. Removing that allows the queries to run, but you end up with conflicts between the two charts sending out queries to the same source for the same data. Since they are both running off the same data, it makes sense to use one query that populates both charts at the same time:
function drawCharts(){
var query = new google.visualization.Query('https://alexandalexaanalytics.appspot.com/query?id=ahdzfmFsZXhhbmRhbGV4YWFuYWx5dGljc3IVCxIIQXBpUXVlcnkYgICAgIDwiwoM&format=data-table-response');
query.setRefreshInterval(3600);
query.send(function (response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var dataTable = response.getDataTable();
var data1 = new google.visualization.ChartWrapper({
"containerId":"Chart1_div",
"dataTable":dataTable,
"refreshInterval":3600,
"chartType":"GeoChart",
"options":{
"width": 630,
"height": 440,
"title": "test"
}
});
data1.draw();
var data2 = new google.visualization.ChartWrapper({
"containerId":"Chart2_div",
"dataTable":dataTable,
"refreshInterval":3600,
"chartType":"ColumnChart",
"options":{
"width": 630,
"height": 440,
"title": "test"
}
});
data2.draw();
});
}
see it working here: http://jsfiddle.net/asgallant/j5eea/
There was a bug in the Google Analytics SuperProxy code which stopped multiple charts from running on a single page. This has now been updated, example html from githb is below.
Loads of thanks to asgallant for looking into this without his comments I wouldnt have know what to search for to answer this.
<! --
Based on demo video: https://www.youtube.com/watch?v=8Or8KIhpsqg
This shows you how to power 2 Pie Charts using the Google Analytics
superProxy. Each chart uses, as a data source, a public superProxy URL
with the format set to Data Table Response.
-->
<html>
<head>
<title>Pie!</title>
<!--Load the AJAX API-->
<script type="text/javascript"
src='https://www.google.com/jsapi?autoload={"modules":[{"name":"visualization","version":"1"}]}'>
</script>
<!-- Visualization -->
<!-- https://developers.google.com/chart/interactive/docs/reference#google.visualization.drawchart -->
<script type="text/javascript">
google.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var browserWrapper = new google.visualization.ChartWrapper({
// Example Browser Share Query
"containerId": "browser",
// Example URL: http://your-application-id.appspot.com/query?id=QUERY_ID&format=data-table-response
"dataSourceUrl": "REPLACE WITH Google Analytics superProxy PUBLIC URL, DATA TABLE RESPONSE FORMAT",
"refreshInterval": REPLACE_WITH_A_TIME_INTERVAL,
"chartType": "PieChart",
"options": {
"showRowNumber" : true,
"width": 630,
"height": 440,
"is3D": true,
"title": "REPLACE WITH TITLE"
}
});
var countryWrapper = new google.visualization.ChartWrapper({
// Example Country Share Query
"containerId": "country",
"dataSourceUrl": "REPLACE WITH Google Analytics superProxy PUBLIC URL, DATA TABLE RESPONSE FORMAT",
"refreshInterval": REPLACE_WITH_A_TIME_INTERVAL,
"chartType": "PieChart",
"options": {
"showRowNumber" : true,
"width": 630,
"height": 440,
"is3D": true,
"title": "REPLACE WITH TITLE"
}
});
browserWrapper.draw();
countryWrapper.draw();
}
</script>
</head>
<body>
<h1>Pie!</h1>
<div id="browser" style="margin:auto;width:630px;"></div>
<div id="country" style="margin:auto;width:630px;"></div>
</body>
</html>