This sample demonstrates how to add and delete items in a user’s portal.

Use case
Portals allow you to share and publish data with others. For example, you may create or collect some data on your device and want to upload that to a cloud storage location to share with others or simply save for later use. In this case, a CSV file is created and uploaded to ArcGIS Online.
How to use the sample
- Press the Authenticate Portal button and sign into your ArcGIS Online account.
- Press the Add Item button, and this will add the CSV to your
Portal. - Press the Delete Item button, and this will delete that same item from your
Portal.
How it works
- A
Portalis created with aCredentialusingOAuthModeUser. ThePortalinstance is loaded and the OAuth sign in page is displayed. The user must now provide credentials. - Once the sign-in process is complete, a
PortalItemof typeCSVis created using thisPortalinstance. - When the portal is successfully loaded, the
PortalUserobject is obtained from thePortal. - When the “Add Item” button is clicked, the item is added via the
PortalUser’saddPortalItemWithUrlAsyncmethod. ThePortalItemand the local URL of the CSV file are supplied as parameters. - When the item has been successfully added, it is loaded in order to retrieve online properties such as the
itemId.’ - When the “Delete Item” button is clicked, the item is passed as a parameter for the portalUser’s
deleteItemAsyncmethod.
Relevant API
- Portal
- PortalItem
- PortalUser::addPortalItemWithUrlAsync
- PortalUser::deleteItemAsync
Tags
add item, cloud, portal
Sample Code
// [WriteFile Name=AddItemsToPortal, Category=CloudAndPortal]// [Legal]// Copyright 2016 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
#ifdef PCH_BUILD#include "pch.hpp"#endif // PCH_BUILD
// sample headers#include "AddItemsToPortal.h"
// ArcGIS Maps SDK headers#include "Authentication/OAuthUserConfiguration.h"#include "Error.h"#include "ErrorException.h"#include "ErrorInformationKeys.h"#include "MapTypes.h"#include "Portal.h"#include "PortalItem.h"#include "PortalItemListModel.h"#include "PortalTypes.h"#include "PortalUser.h"
// Qt headers#include <QFuture>#include <QVariantMap>
// Other headers#include "OAuthUserConfigurationManager.h"
using namespace Esri::ArcGISRuntime;using namespace Esri::ArcGISRuntime::Authentication;using namespace Esri::ArcGISRuntime::Toolkit;
AddItemsToPortal::AddItemsToPortal(QQuickItem* parent /* = nullptr */): QQuickItem(parent), m_portal(new Portal(true, this)){ const QString redirectUrl{"urn:ietf:wg:oauth:2.0:oob"}; OAuthUserConfiguration* config = new OAuthUserConfiguration(m_portal->url(), "iLkGIj0nX8A4EJda", redirectUrl, this); OAuthUserConfigurationManager::addConfiguration(config);
m_item = new PortalItem(m_portal, PortalItemType::CSV, this); m_item->setTitle("Add Items Sample");}
AddItemsToPortal::~AddItemsToPortal() = default;
void AddItemsToPortal::init(){ // Register the types for QML qmlRegisterType<AddItemsToPortal>("Esri.Samples", 1, 0, "AddItemsToPortalSample");}
void AddItemsToPortal::componentComplete(){ QQuickItem::componentComplete();
if (m_portal) { connect(m_portal, &Portal::loadStatusChanged, this, [this]() { emit portalLoadedChanged();
if (m_portal->loadStatus() != LoadStatus::Loaded) return;
m_user = m_portal->portalUser(); m_busy = false; connectUserSignals(); }); }
if (m_item) { connect(m_item, &PortalItem::loadStatusChanged, this, [this]() { if (m_item->loadStatus() != LoadStatus::Loaded) return;
m_busy = false; emit portalItemIdChanged(); emit portalItemTitleChanged(); emit portalItemLoadedChanged(); if (m_alreadyExisted) setStatusText("Item already exists; using existing item instead. " + m_item->itemId()); else setStatusText("Succesfully loaded item from portal. " + m_item->itemId()); }); }}
bool AddItemsToPortal::portalLoaded() const{ return m_portal && (m_portal->loadStatus() == LoadStatus::Loaded);}
bool AddItemsToPortal::portalItemLoaded() const{ return m_item && (m_item->loadStatus() == LoadStatus::Loaded);}
QString AddItemsToPortal::portalItemId() const{ if (m_itemDeleted || !m_item) return QString();
return m_item->itemId();}
QString AddItemsToPortal::portalItemTitle() const{ if (m_itemDeleted || !m_item) return QString();
return m_item->title();}
QString AddItemsToPortal::portalItemTypeName() const{ if (m_itemDeleted || !m_item) return QString();
return m_item->typeName();}
bool AddItemsToPortal::itemDeleted() const{ return m_itemDeleted;}
QString AddItemsToPortal::statusText() const{ return m_statusText;}
bool AddItemsToPortal::busy() const{ return m_busy;}
void AddItemsToPortal::authenticatePortal(){ if (!m_portal) return; if (m_portal->loadStatus() == LoadStatus::FailedToLoad) m_portal->retryLoad(); else m_portal->load();}
void AddItemsToPortal::addItem(){ if (!m_user || !m_item) return;
m_busy = true;
//! [PortalUser addItemWithUrlAsync] QUrl localCSV("qrc:/Samples/CloudAndPortal/AddItemsToPortal/add_item_sample.csv"); m_user->addPortalItemWithUrlAsync(m_item, localCSV, "add_item_sample.csv" ).then(this, [this]() { m_busy = false;
setStatusText("Successfully added item. " + m_item->itemId()); m_item->load(); }) //! [PortalUser addItemWithUrlAsync] .onFailed( [this](const ErrorException& e) { m_busy = false;
// Check for service error 409 "Conflict" - item already exists const QVariantMap additionalInfo = e.error().additionalInformation(); if (additionalInfo.contains(ErrorInformationKeys::serviceError()) && additionalInfo.value(ErrorInformationKeys::serviceError()).toInt() == 409) { m_alreadyExisted = true; setStatusText("Item already exists; fetching existing item instead. " + m_item->itemId()); fetchItem(); } else { setStatusText(e.error().message()); } });}
void AddItemsToPortal::deleteItem(){ if (!m_user || !m_item) return;
m_busy = true;
m_user->deletePortalItemAsync(m_item).then(this, [this]() { m_busy = false; m_itemDeleted = true;
emit itemDeletedChanged(); emit portalItemIdChanged(); emit portalItemTitleChanged(); emit portalItemTypeNameChanged();
setStatusText("Successfully deleted item. " + m_item->itemId()); }).onFailed( [this](const ErrorException& e) { m_busy = false;
setStatusText(e.error().message()); });}
void AddItemsToPortal::fetchItem(){ if (!m_user || !m_item) return;
m_busy = true;
m_user->fetchContentAsync().then(this, [this]() { m_busy = false;
for (PortalItem* item : *m_user->items()) { if (item->title() == "Add Items Sample") { m_item->setItemId(item->itemId()); m_item->load(); return; } } });}
void AddItemsToPortal::connectUserSignals(){ if (!m_user) return;
connect(m_user, &PortalUser::errorOccurred, this, [this](const Error& error) { m_busy = false; setStatusText(QString(error.message() + ": " + error.additionalMessage())); });}
void AddItemsToPortal::setStatusText(const QString &statusText){ m_statusText = statusText; emit statusTextChanged();}// [WriteFile Name=AddItemsToPortal, Category=CloudAndPortal]// [Legal]// Copyright 2016 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
#ifndef ADDITEMSTOPORTAL_H#define ADDITEMSTOPORTAL_H
// Qt headers#include <QQuickItem>
namespace Esri::ArcGISRuntime{ class Portal; class PortalItem; class PortalUser;}
class AddItemsToPortal : public QQuickItem{ Q_OBJECT
Q_PROPERTY(bool portalLoaded READ portalLoaded NOTIFY portalLoadedChanged) Q_PROPERTY(bool portalItemLoaded READ portalItemLoaded NOTIFY portalItemLoadedChanged) Q_PROPERTY(QString portalItemId READ portalItemId NOTIFY portalItemIdChanged) Q_PROPERTY(QString portalItemTitle READ portalItemTitle NOTIFY portalItemTitleChanged) Q_PROPERTY(QString portalItemTypeName READ portalItemTypeName NOTIFY portalItemTypeNameChanged) Q_PROPERTY(bool itemDeleted READ itemDeleted NOTIFY itemDeletedChanged) Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged) Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
public: explicit AddItemsToPortal(QQuickItem* parent = nullptr); ~AddItemsToPortal() override;
void componentComplete() override; static void init();
Q_INVOKABLE void authenticatePortal(); Q_INVOKABLE void addItem(); Q_INVOKABLE void deleteItem();
signals: void portalLoadedChanged(); void portalItemLoadedChanged(); void portalItemTitleChanged(); void portalItemIdChanged(); void portalItemTypeNameChanged(); void itemDeletedChanged(); void statusTextChanged(); void busyChanged();
private: void fetchItem(); bool portalLoaded() const; bool portalItemLoaded() const; QString portalItemId() const; QString portalItemTitle() const; QString portalItemTypeName() const; bool itemDeleted() const; QString statusText() const; bool busy() const;
void setStatusText(const QString& msg); void connectUserSignals();
Esri::ArcGISRuntime::Portal* m_portal = nullptr; Esri::ArcGISRuntime::PortalItem* m_item = nullptr; Esri::ArcGISRuntime::PortalUser* m_user = nullptr; bool m_itemDeleted = false; QString m_statusText; bool m_busy = false; bool m_alreadyExisted = false;};
#endif // ADDITEMSTOPORTAL_H// [WriteFile Name=AddItemsToPortal, Category=CloudAndPortal]// [Legal]// Copyright 2016 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
import QtQuickimport QtQuick.Controlsimport Esri.Samplesimport Esri.ArcGISRuntime.Toolkit
AddItemsToPortalSample { id: rootRectangle clip: true width: 800 height: 600
onPortalItemTitleChanged: portalItemModel.setProperty(0, "value", portalItemTitle); onPortalItemIdChanged: portalItemModel.setProperty(1, "value", portalItemId); onPortalItemTypeNameChanged: portalItemModel.setProperty(2, "value", portalItemTypeName);
Flickable { anchors.fill: parent interactive: true boundsBehavior: Flickable.StopAtBounds contentHeight: parent.height * 1.5 contentWidth: parent.width Column { anchors { fill: parent margins: 16 } spacing: 16
Rectangle { id: authenticationButton anchors.horizontalCenter: parent.horizontalCenter height: 64 width: Math.min(256, parent.width) color: enabled ? "darkblue" : "darkgrey" border{ color: "lightgrey" width: 2 } radius: 8 enabled: !portalLoaded
Row { anchors.fill: parent spacing: 16
Image { anchors.verticalCenter: parent.verticalCenter source: !portalLoaded ? "qrc:/Samples/CloudAndPortal/AddItemsToPortal/ic_menu_account_dark.png" : "qrc:/Samples/CloudAndPortal/AddItemsToPortal/ic_menu_checkedcircled_dark.png" fillMode: Image.PreserveAspectFit height: 64 width: height }
Text { anchors.verticalCenter: parent.verticalCenter text: "Authenticate Portal" font.bold: true color: "white" } }
MouseArea { anchors.fill: parent onClicked: { authenticatePortal(); authenticationButton.border.width = 4; } } }
Rectangle { id: addItemButton anchors.horizontalCenter: parent.horizontalCenter height: authenticationButton.height width: authenticationButton.width color: enabled ? "darkblue" : "darkgrey" border{ color: authenticationButton.border.color width: 2 } radius: authenticationButton.radius enabled: !portalItemLoaded && portalLoaded
Row { anchors.fill: parent spacing: 16
Image { anchors.verticalCenter: parent.verticalCenter source: portalItemLoaded ? "qrc:/Samples/CloudAndPortal/AddItemsToPortal/ic_menu_checkedcircled_dark.png" : "qrc:/Samples/CloudAndPortal/AddItemsToPortal/ic_menu_addencircled_dark.png"
fillMode: Image.PreserveAspectFit height: 64 width: height }
Text { anchors.verticalCenter: parent.verticalCenter text: "Add Item" font.bold: true color: "white" } }
MouseArea { anchors.fill: parent onClicked: { addItemButton.border.width = 4 addItem(); } } }
Rectangle { id: deleteItemButton anchors.horizontalCenter: parent.horizontalCenter height: authenticationButton.height width: authenticationButton.width color: enabled ? "darkblue" : "darkgrey" border { color: authenticationButton.border.color width: 2 } radius: authenticationButton.radius enabled: portalItemLoaded && !itemDeleted
Row { anchors.fill: parent spacing: 16
Image { anchors.verticalCenter: parent.verticalCenter source: !itemDeleted ? "qrc:/Samples/CloudAndPortal/AddItemsToPortal/ic_menu_trash_dark.png" : "qrc:/Samples/CloudAndPortal/AddItemsToPortal/ic_menu_checkedcircled_dark.png"
fillMode: Image.PreserveAspectFit height: 64 width: height }
Text { anchors.verticalCenter: parent.verticalCenter text: "Delete Item" font.bold: true color: "white" } }
MouseArea { anchors.fill: parent onClicked: { deleteItemButton.border.width = 2 deleteItem(); } } }
Rectangle { anchors { left: parent.left right: parent.right } height: 4 color: "lightgrey" }
Rectangle { id: itemView anchors { left: parent.left right: parent.right } height: 128 color: "lightsteelblue" border { color: "darkgrey" width: 4 } radius: 32 clip: true
Text { id: portalItemLabel anchors{ top: parent.top horizontalCenter: parent.horizontalCenter margins: 4 } color: "white" font.bold: true text: "PortalItem" font.underline: true horizontalAlignment: Text.AlignHCenter }
ListModel { id: portalItemModel
Component.onCompleted: { append({"label": "title", "value": portalItemTitle }); append({"label": "itemId", "value": portalItemId}); append({"label": "type", "value": portalItemTypeName}); } }
ListView { anchors { top: portalItemLabel.bottom left: parent.left right: parent.right bottom: parent.bottom margins: 16 } clip: true model: portalItemModel delegate: Text { color: "white" text: label + ":\t" + value wrapMode: Text.Wrap elide: Text.ElideRight } } }
Text { id: statusBar anchors{ left: parent.left right: parent.right } wrapMode: Text.Wrap elide: Text.ElideRight text: statusText } } }
// Declare Authenticator to handle any authentication challenges Authenticator { anchors.fill: parent }
BusyIndicator { anchors.centerIn: parent running: busy }}// [Legal]// Copyright 2015 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
// Qt headers#include <QCommandLineParser>#include <QDir>#include <QGuiApplication>#include <QQmlEngine>#include <QQuickView>
#ifdef QT_WEBVIEW_WEBENGINE_BACKEND#include <QtWebEngineQuick>#endif // QT_WEBVIEW_WEBENGINE_BACKEND
#include "Esri/ArcGISRuntime/Toolkit/register.h"#include "ArcGISRuntimeEnvironment.h"
#ifdef Q_OS_WIN#include <Windows.h>#endif
#include "AddItemsToPortal.h"
#define STRINGIZE(x) #x#define QUOTE(x) STRINGIZE(x)
int main(int argc, char *argv[]){ Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setUseLegacyAuthentication(false);#ifdef QT_WEBVIEW_WEBENGINE_BACKEND QtWebEngineQuick::initialize();#endif // QT_WEBVIEW_WEBENGINE_BACKEND
QGuiApplication app(argc, argv); app.setApplicationName(QString("Add Items to Portal"));
// Initialize the sample AddItemsToPortal::init();
// Initialize application view QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView);
// Add the import Path view.engine()->addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml"));
QString arcGISRuntimeImportPath = QUOTE(ARCGIS_RUNTIME_IMPORT_PATH);
#if defined(LINUX_PLATFORM_REPLACEMENT) // on some linux platforms the string 'linux' is replaced with 1 // fix the replacement paths which were created QString replaceString = QUOTE(LINUX_PLATFORM_REPLACEMENT); arcGISRuntimeImportPath = arcGISRuntimeImportPath.replace(replaceString, "linux", Qt::CaseSensitive); #endif
// Add the Runtime and Extras path view.engine()->addImportPath(arcGISRuntimeImportPath);
Esri::ArcGISRuntime::Toolkit::registerComponents(*(view.engine()));
// Set the source view.setSource(QUrl("qrc:/Samples/CloudAndPortal/AddItemsToPortal/AddItemsToPortal.qml"));
view.show();
return app.exec();}