Plugin for Tree Table with folder hierarchy & folder uploads
This example demonstrates the usage of UploadSetwithTable plugin with a tree table featuring folder hierarchy, folder creation, folder uploads, folder navigation with breadcrumbs and folder management
Z2UI5_CL_SMPC_APP_661
The facts
- Repository
- abap2UI5/samples-controls
- Class
Z2UI5_CL_SMPC_APP_661- Source file
z2ui5_cl_smpc_app_661.clas.abap↗- Library
- sap.m
- UI5 entity
sap.m.plugins.UploadSetwithTable- Demo kit sample
sap.m.sample.UploadSetwithTablePlugin.TreeTableWithFolderHierarchy- SAP's own sample
- running at sdk.openui5.org ↗
- Minimum UI5
- 1.139
- In the playground
- runs in the browser, with no system and nothing installed
Keywords: uploadsetwithtable, upload, setwith, table, sap.m.plugins, treetablewithfolderhierarchy, dynamicpage, treetable, overflowtoolbar, breadcrumbs, link, actionsplaceholder
Controls it builds
- sap.f.DynamicPage
- sap.m.Breadcrumbs
- sap.m.Button
- sap.m.Dialog
- sap.m.HBox
- sap.m.Image
- sap.m.Input
- sap.m.Label
- sap.m.Link
- sap.m.OverflowToolbar
- sap.m.Text
- sap.m.VBox
- sap.m.plugins.UploadSetwithTable
- sap.m.upload.ActionsPlaceholder
- sap.m.upload.UploadItemConfiguration
- sap.ui.core.FragmentDefinition
- sap.ui.core.Icon
- sap.ui.core.mvc.View
- sap.ui.table.Column
- sap.ui.table.RowSettings
- sap.ui.table.TreeTable
Read out of the builder chain by the abap2UI5 linter, not from the category this sample is filed under — which is what makes “which samples build one of these” a question the catalogue can answer at all.
Libraries
Run it here
Nothing is installed and nothing is sent anywhere: the ABAP is compiled to JavaScript in this browser and runs against abap2UI5 itself.
The ABAP
" @keywords uploadsetwithtable upload setwith table sap.m.plugins treetablewithfolderhierarchy dynamicpage treetable overflowtoolbar breadcrumbs link actionsplaceholder
" @summary This example demonstrates the usage of UploadSetwithTable plugin with a tree table featuring folder hierarchy, folder creation, folder uploads, folder navigation with breadcrumbs and folder management
" @origin sap.m.sample.UploadSetwithTablePlugin.TreeTableWithFolderHierarchy - https://sdk.openui5.org/entity/sap.m.plugins.UploadSetwithTable/sample/sap.m.sample.UploadSetwithTablePlugin.TreeTableWithFolderHierarchy (status: generated)
CLASS z2ui5_cl_smpc_app_661 DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
" the rows the TreeTable shows: the open folder's content, four levels deep
TYPES:
BEGIN OF ty_s_level4,
documentid TYPE string,
filename TYPE string,
mimetype TYPE string,
imageurl TYPE string,
url TYPE string,
size TYPE i,
uploadeddate TYPE string,
uploadedby TYPE string,
isdirectory TYPE abap_bool,
status TYPE string,
documenttype TYPE string,
previewable TYPE abap_bool,
trustedsource TYPE abap_bool,
color TYPE string,
bgcolor TYPE string,
uploadstate TYPE string,
icon TYPE string,
size_units TYPE string,
END OF ty_s_level4.
TYPES ty_t_level4 TYPE STANDARD TABLE OF ty_s_level4 WITH EMPTY KEY.
TYPES:
BEGIN OF ty_s_level3,
documentid TYPE string,
filename TYPE string,
mimetype TYPE string,
imageurl TYPE string,
url TYPE string,
size TYPE i,
uploadeddate TYPE string,
uploadedby TYPE string,
isdirectory TYPE abap_bool,
status TYPE string,
documenttype TYPE string,
previewable TYPE abap_bool,
trustedsource TYPE abap_bool,
color TYPE string,
bgcolor TYPE string,
uploadstate TYPE string,
icon TYPE string,
size_units TYPE string,
items TYPE ty_t_level4,
END OF ty_s_level3.
TYPES ty_t_level3 TYPE STANDARD TABLE OF ty_s_level3 WITH EMPTY KEY.
TYPES:
BEGIN OF ty_s_level2,
documentid TYPE string,
filename TYPE string,
mimetype TYPE string,
imageurl TYPE string,
url TYPE string,
size TYPE i,
uploadeddate TYPE string,
uploadedby TYPE string,
isdirectory TYPE abap_bool,
status TYPE string,
documenttype TYPE string,
previewable TYPE abap_bool,
trustedsource TYPE abap_bool,
color TYPE string,
bgcolor TYPE string,
uploadstate TYPE string,
icon TYPE string,
size_units TYPE string,
items TYPE ty_t_level3,
END OF ty_s_level2.
TYPES ty_t_level2 TYPE STANDARD TABLE OF ty_s_level2 WITH EMPTY KEY.
TYPES:
BEGIN OF ty_s_level1,
documentid TYPE string,
filename TYPE string,
mimetype TYPE string,
imageurl TYPE string,
url TYPE string,
size TYPE i,
uploadeddate TYPE string,
uploadedby TYPE string,
isdirectory TYPE abap_bool,
status TYPE string,
documenttype TYPE string,
previewable TYPE abap_bool,
trustedsource TYPE abap_bool,
color TYPE string,
bgcolor TYPE string,
uploadstate TYPE string,
icon TYPE string,
size_units TYPE string,
items TYPE ty_t_level2,
END OF ty_s_level1.
TYPES:
BEGIN OF ty_s_history,
name TYPE string,
path TYPE string,
END OF ty_s_history.
DATA t_items TYPE STANDARD TABLE OF ty_s_level1 WITH EMPTY KEY.
DATA currentlocationtext TYPE string.
DATA t_history TYPE STANDARD TABLE OF ty_s_history WITH EMPTY KEY.
" onSelectionChange's three buttons
DATA download_enabled TYPE abap_bool.
DATA rename_enabled TYPE abap_bool.
DATA removeall_enabled TYPE abap_bool.
" the CreateFolderDialog fragment and the controller-built Rename Folder dialog
DATA folder_name TYPE string.
DATA rename_name TYPE string.
PROTECTED SECTION.
" the whole documents.json tree, flat: every node names its parent folder
TYPES:
BEGIN OF ty_s_doc,
parentid TYPE string,
documentid TYPE string,
filename TYPE string,
mimetype TYPE string,
imageurl TYPE string,
url TYPE string,
size TYPE i,
uploadeddate TYPE string,
uploadedby TYPE string,
isdirectory TYPE abap_bool,
status TYPE string,
documenttype TYPE string,
previewable TYPE abap_bool,
trustedsource TYPE abap_bool,
color TYPE string,
bgcolor TYPE string,
uploadstate TYPE string,
icon TYPE string,
size_units TYPE string,
END OF ty_s_doc.
TYPES ty_t_index TYPE STANDARD TABLE OF i WITH EMPTY KEY.
DATA client TYPE REF TO z2ui5_if_client.
DATA t_docs TYPE STANDARD TABLE OF ty_s_doc WITH EMPTY KEY.
" the folder the table shows - initial is the root, Attachments
DATA current_id TYPE string.
" the documentIds of the selected rows, of the row a removal asks about and
" of the folder being renamed
DATA t_selected TYPE string_table.
DATA remove_id TYPE string.
DATA rename_id TYPE string.
DATA new_no TYPE i.
METHODS view_display.
METHODS popup_folder_display.
METHODS popup_rename_display.
METHODS on_event.
METHODS selection_set
IMPORTING
paths TYPE string.
METHODS download.
METHODS folder_create
IMPORTING
name TYPE string.
METHODS folder_open
IMPORTING
id TYPE string.
METHODS remove_all_ask.
METHODS remove_selected.
METHODS rows_build.
METHODS children_count
IMPORTING
parent TYPE string
RETURNING
VALUE(result) TYPE i.
METHODS doc_at_path
IMPORTING
path TYPE string
RETURNING
VALUE(result) TYPE string.
METHODS doc_delete
IMPORTING
id TYPE string.
METHODS doc_insert
IMPORTING
doc TYPE ty_s_doc
after_folders TYPE abap_bool.
METHODS path_indices
IMPORTING
path TYPE string
RETURNING
VALUE(result) TYPE ty_t_index.
METHODS row_derive
CHANGING
row TYPE ty_s_doc.
METHODS icon_for
IMPORTING
mediatype TYPE string
filename TYPE string
RETURNING
VALUE(result) TYPE string.
METHODS size_with_units
IMPORTING
size TYPE i
RETURNING
VALUE(result) TYPE string.
METHODS model_init.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_smpc_app_661 IMPLEMENTATION.
METHOD z2ui5_if_app~main.
me->client = client.
IF client->check_on_init( ).
model_init( ).
view_display( ).
ELSEIF client->check_on_navigated( ).
view_display( ).
ELSEIF client->check_on_event( ).
on_event( ).
ENDIF.
ENDMETHOD.
METHOD view_display.
DATA(view) = z2ui5_cl_ui5_view_builder=>factory( ).
view->ele( n = `View` ns = `mvc`
)->a( n = `xmlns` v = `sap.ui.table`
)->a( n = `xmlns:m` v = `sap.m`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
)->a( n = `xmlns:f` v = `sap.f`
)->a( n = `xmlns:core` v = `sap.ui.core`
)->a( n = `xmlns:upload` v = `sap.m.upload`
)->a( n = `xmlns:plugins` v = `sap.m.plugins`
)->a( n = `height` v = `100%`
)->a( n = `displayBlock` v = `true`
)->ele( n = `DynamicPage` ns = `f`
)->a( n = `id` v = `page`
)->ele( n = `content` ns = `f`
" onToggleOpenState is an empty handler - the wire is not built
)->ele( `TreeTable`
)->a( n = `id` v = `table-uploadSet`
" IMAGEURL and UPLOADSTATE stay absent where the data has none, so
" the view's undefined checks read as in the sample
)->a( n = `rows` v = client->_bind( val = t_items
omit_initial_paths = VALUE #( ( `IMAGEURL` )
( `UPLOADSTATE` ) ) )
)->a( n = `selectionMode` v = `MultiToggle`
)->a( n = `rowSelectionChange` v = client->_event( val = `SELECTION`
arg = `$event.oSource.getBinding('rows').getSelectedContexts().join()` )
)->ele( `extension`
)->ele( n = `OverflowToolbar` ns = `m`
)->a( n = `style` v = `Clear`
)->ele( n = `Breadcrumbs` ns = `m`
)->a( n = `id` v = `breadcrumbs`
)->a( n = `currentLocationText` v = client->_bind( currentlocationtext )
)->a( n = `links` v = client->_bind( t_history )
)->tag( n = `Link` ns = `m`
)->a( n = `press` v = client->_event( val = `CRUMB`
arg = `$event.oSource.getBindingContext().getPath()` )
)->a( n = `text` v = `{NAME}`
)->end(
)->tag( n = `ActionsPlaceholder` ns = `upload`
)->a( n = `id` v = `uploadButton`
)->a( n = `placeholderFor` v = `UploadButtonPlaceholder`
)->tag( n = `Button` ns = `m`
)->a( n = `id` v = `downloadSelectedButton`
)->a( n = `text` v = `Download`
)->a( n = `enabled` v = client->_bind( download_enabled )
)->a( n = `press` v = client->_event( `DOWNLOAD` )
)->tag( n = `Button` ns = `m`
)->a( n = `id` v = `addFolderButton`
)->a( n = `text` v = `Add Folder`
)->a( n = `press` v = client->_event( `ADD_FOLDER` )
)->a( n = `icon` v = `sap-icon://add-folder`
" onRenameItem: a folder gets the controller's dialog (backend), a file
" the plugin's renameItem - the second handler hands it the selected
" context, or null for a folder, which renameItem ignores
)->tag( n = `Button` ns = `m`
)->a( n = `id` v = `renameButton`
)->a( n = `text` v = `Rename`
)->a( n = `enabled` v = client->_bind( rename_enabled )
)->a( n = `press` v = client->_event( `RENAME` ) && `; ` &&
client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `uploadPlugin` )
( `renameItem` )
( `$controller.getView().byId('table-uploadSet').getBinding('rows')` &&
`.getSelectedContexts()[0].getProperty('ISDIRECTORY') ? null : ` &&
`$controller.getView().byId('table-uploadSet').getBinding('rows')` &&
`.getSelectedContexts()[0]` ) ) )
)->tag( n = `Button` ns = `m`
)->a( n = `id` v = `removeAllButton`
)->a( n = `text` v = `Remove All`
)->a( n = `enabled` v = client->_bind( removeall_enabled )
)->a( n = `press` v = client->_event( `REMOVE_ALL` )
)->end(
)->end(
)->ele( `dependents`
)->ele( n = `UploadSetwithTable` ns = `plugins`
)->a( n = `id` v = `uploadPlugin`
)->a( n = `uploadUrl` v = `./uploadFiles`
)->a( n = `multiple` v = `true`
)->a( n = `uploadEnabled` v = `true`
" the mock server's part: the upload is vetoed and the backend
" files the document into the open folder
)->a( n = `beforeUploadStarts` v = client->_event( val = `UPLOAD`
t_arg = VALUE #( ( `${$parameters>/item}.getFileName()` )
( `${$parameters>/item}.getMediaType()` )
( `${$parameters>/item}.getFileObject().size` ) )
s_ctrl = VALUE #( check_prevent_default = abap_true
check_queue_last = abap_true ) )
)->a( n = `itemRenamed` v = client->_event( val = `RENAMED`
t_arg = VALUE #( ( `${$parameters>/item}.getBindingContext().getPath()` )
( `${$parameters>/item}.getFileName()` ) ) )
)->a( n = `actions` v = `uploadButton`
" the paths name the model's upper-case ABAP fields
)->tag( n = `UploadItemConfiguration` ns = `upload`
)->a( n = `fileNamePath` v = `FILENAME`
)->a( n = `mediaTypePath` v = `MIMETYPE`
)->a( n = `urlPath` v = `URL`
)->a( n = `fileSizePath` v = `SIZE`
)->a( n = `isDirectoryPath` v = `ISDIRECTORY`
)->a( n = `previewablePath` v = `PREVIEWABLE`
)->a( n = `isTrustedSourcePath` v = `TRUSTEDSOURCE`
)->end(
)->end(
)->ele( `rowSettingsTemplate`
)->tag( `RowSettings`
)->a( n = `highlight` v = `{= ${UPLOADSTATE} === 'Complete' ? 'Indication05' : null }`
)->end(
)->ele( `columns`
)->ele( `Column`
)->a( n = `width` v = `40%`
)->tag( n = `Label` ns = `m`
)->a( n = `text` v = `File Name`
)->ele( `template`
)->ele( n = `HBox` ns = `m`
)->a( n = `class` v = `sapUiSmallMarginTop sapUiTinyMarginBottom`
)->tag( n = `Image` ns = `m`
)->a( n = `src` v = `{IMAGEURL}`
)->a( n = `class` v = `sapMUSTItemImage sapMUSTItemIcon`
)->a( n = `visible` v = `{= ${IMAGEURL} !== undefined}`
" getIconSrc runs in ABAP: the row carries the finished icon
)->tag( n = `Icon` ns = `core`
)->a( n = `src` v = `{ICON}`
)->a( n = `visible` v = `{= ${IMAGEURL} === undefined || ${IMAGEURL} === '' }`
)->a( n = `class` v = `sapMUSTItemIcon`
)->a( n = `color` v = `{= ${ISDIRECTORY} ? ${COLOR} : '' }`
)->a( n = `backgroundColor` v = `{= ${ISDIRECTORY} ? ${BGCOLOR} : '' }`
)->ele( n = `VBox` ns = `m`
)->a( n = `class` v = `sapUiTinyMargin sapUiSmallMarginBegin`
)->tag( n = `Link` ns = `m`
)->a( n = `text` v = `{FILENAME}`
)->a( n = `press` v = client->_event( val = `OPEN_FOLDER`
arg = `$event.oSource.getBindingContext().getPath()` )
)->a( n = `class` v = `sapUiSmallMarginBottom`
)->a( n = `visible` v = `{= ${ISDIRECTORY} === true }`
)->tag( n = `Link` ns = `m`
)->a( n = `text` v = `{FILENAME}`
)->a( n = `press` v = client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `uploadPlugin` )
( `openFilePreview` )
( `$event.oSource.getBindingContext()` ) ) )
)->a( n = `class` v = `sapUiTinyMarginBottom`
)->a( n = `visible` v = `{= ${ISDIRECTORY} === false }`
)->tag( n = `Text` ns = `m`
)->a( n = `text` v = `{DOCUMENTTYPE}`
)->end(
)->end(
)->end(
)->end(
)->ele( `Column`
)->tag( n = `Label` ns = `m`
)->a( n = `text` v = `Status`
)->ele( `template`
)->tag( n = `Text` ns = `m`
)->a( n = `text` v = `{STATUS}`
)->end(
)->end(
)->ele( `Column`
)->tag( n = `Label` ns = `m`
)->a( n = `text` v = `File Size`
" formatFileSize runs in ABAP as well
)->ele( `template`
)->tag( n = `Text` ns = `m`
)->a( n = `text` v = `{SIZE_UNITS}`
)->end(
)->end(
)->ele( `Column`
)->tag( n = `Label` ns = `m`
)->a( n = `text` v = `Last Modified`
)->ele( `template`
)->ele( n = `VBox` ns = `m`
)->tag( n = `Text` ns = `m`
)->a( n = `text` v = `{UPLOADEDBY}`
)->tag( n = `Text` ns = `m`
)->a( n = `class` v = `sapUiTinyMarginTop`
)->a( n = `text` v = `{UPLOADEDDATE}`
)->end(
)->end(
)->end(
)->ele( `Column`
)->ele( `template`
)->tag( n = `Button` ns = `m`
)->a( n = `class` v = `sapUiTinyMarginBegin`
)->a( n = `type` v = `Transparent`
)->a( n = `icon` v = `sap-icon://decline`
)->a( n = `press` v = client->_event( val = `REMOVE_ROW`
arg = `$event.oSource.getBindingContext().getPath()` )
)->a( n = `visible` v = `{= ${ISDIRECTORY} === false }`
)->a( n = `tooltip` v = `Delete File` ).
client->view_display( view->stringify( ) ).
ENDMETHOD.
METHOD popup_folder_display.
DATA(popup) = z2ui5_cl_ui5_view_builder=>factory( ).
popup->ele( n = `FragmentDefinition` ns = `core`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:core` v = `sap.ui.core`
)->ele( `Dialog`
)->a( n = `title` v = `Create New Folder`
)->a( n = `class` v = `sapUiMediumMargin`
)->ele( `content`
)->ele( `VBox`
)->a( n = `class` v = `sapUiMediumMargin`
)->tag( `Label`
)->a( n = `text` v = `Folder name:`
)->tag( `Input`
)->a( n = `id` v = `folderNameInput`
)->a( n = `value` v = client->_bind( folder_name )
)->a( n = `placeholder` v = `Enter folder name`
)->end(
)->end(
)->ele( `buttons`
)->tag( `Button`
)->a( n = `text` v = `Create`
)->a( n = `type` v = `Emphasized`
)->a( n = `press` v = client->_event( `CREATE_FOLDER` )
)->tag( `Button`
)->a( n = `text` v = `Cancel`
)->a( n = `press` v = client->follow_up_action( client->cs_event-popup_close ) ).
client->popup_display( popup->stringify( ) ).
ENDMETHOD.
METHOD popup_rename_display.
" renameFolderWithDialog builds this Dialog in the controller
DATA(popup) = z2ui5_cl_ui5_view_builder=>factory( ).
popup->ele( n = `FragmentDefinition` ns = `core`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:core` v = `sap.ui.core`
)->ele( `Dialog`
)->a( n = `title` v = `Rename Folder`
)->ele( `content`
)->tag( `Input`
)->a( n = `value` v = client->_bind( rename_name )
)->a( n = `width` v = `100%`
)->end(
)->ele( `beginButton`
)->tag( `Button`
)->a( n = `text` v = `OK`
)->a( n = `type` v = `Emphasized`
)->a( n = `press` v = client->_event( `RENAME_FOLDER_OK` )
)->end(
)->ele( `endButton`
)->tag( `Button`
)->a( n = `text` v = `Cancel`
)->a( n = `press` v = client->follow_up_action( client->cs_event-popup_close ) ).
client->popup_display( popup->stringify( ) ).
ENDMETHOD.
METHOD on_event.
CASE client->get_event( ).
WHEN `SELECTION`.
selection_set( client->get_event_arg( ) ).
WHEN `DOWNLOAD`.
download( ).
WHEN `ADD_FOLDER`.
" onCreateFolder - the dialog opens with an empty name
folder_name = ``.
popup_folder_display( ).
WHEN `CREATE_FOLDER`.
" onCreateFolderDialogPress - an empty name keeps the dialog open
DATA(name) = condense( folder_name ).
IF name IS INITIAL.
client->message_toast_display( `Please enter a folder name` ).
RETURN.
ENDIF.
client->popup_destroy( ).
folder_create( name ).
WHEN `RENAME`.
" onRenameItem - the plugin renames a file (the press's second handler);
" a folder is renamed in the controller's own dialog
IF lines( t_selected ) <> 1.
client->message_toast_display( `Please select exactly one item to rename` ).
RETURN.
ENDIF.
DATA(selected) = t_docs[ documentid = t_selected[ 1 ] ].
IF selected-isdirectory = abap_true.
rename_id = selected-documentid.
rename_name = selected-filename.
popup_rename_display( ).
ENDIF.
WHEN `RENAME_FOLDER_OK`.
DATA(folder) = REF #( t_docs[ documentid = rename_id ] ).
DATA(new_name) = condense( rename_name ).
IF new_name IS NOT INITIAL AND new_name <> folder->filename.
folder->filename = new_name.
rows_build( ).
client->message_toast_display( `Folder renamed successfully` ).
ENDIF.
client->popup_destroy( ).
WHEN `RENAMED`.
" onDocumentRenamedSuccess
DATA(renamed) = doc_at_path( client->get_event_arg( ) ).
IF renamed IS NOT INITIAL.
t_docs[ documentid = renamed ]-filename = client->get_event_arg( 2 ).
rows_build( ).
client->message_toast_display( text = `File renamed successfully` duration = `2000` ).
ENDIF.
WHEN `OPEN_FOLDER`.
" onItemPress - navigateToFolder
folder_open( doc_at_path( client->get_event_arg( ) ) ).
WHEN `CRUMB`.
" onBreadcrumbPress - a link is one level of the history
DATA(crumb) = path_indices( client->get_event_arg( ) ).
IF crumb IS INITIAL OR crumb[ 1 ] > lines( t_history ).
RETURN.
ENDIF.
DATA(entry) = t_history[ crumb[ 1 ] ].
folder_open( entry-path ).
WHEN `REMOVE_ROW`.
" onRemoveItemHandler - files only, the button is hidden on folders
DATA(doc) = t_docs[ documentid = doc_at_path( client->get_event_arg( ) ) ].
IF doc-isdirectory = abap_true.
client->message_toast_display( `Folder deletion is not allowed` ).
RETURN.
ENDIF.
remove_id = doc-documentid.
client->message_box_display( text = |Are you sure you want to delete the file '{ doc-filename }'?|
type = `confirm`
title = `Delete File`
onclose = `REMOVE_CLOSE` ).
WHEN `REMOVE_CLOSE`.
" the file is filtered out of the OPEN folder's items
IF client->get_event_arg( ) = `OK`.
DATA(removed) = t_docs[ documentid = remove_id ]-filename.
DELETE t_docs WHERE documentid = remove_id AND parentid = current_id.
rows_build( ).
client->message_toast_display( |File '{ removed }' deleted successfully| ).
ENDIF.
WHEN `REMOVE_ALL`.
remove_all_ask( ).
WHEN `REMOVE_ALL_CLOSE`.
IF client->get_event_arg( ) = `OK`.
remove_selected( ).
ENDIF.
WHEN `UPLOAD`.
" the mock server files the upload into the open folder, after its folders
new_no = new_no + 1.
DATA(file) = VALUE ty_s_doc( parentid = current_id
documentid = |upload-{ new_no }|
filename = client->get_event_arg( )
mimetype = client->get_event_arg( 2 )
size = CONV #( client->get_event_arg( 3 ) )
uploadeddate = |{ sy-datum DATE = ISO }|
uploadedby = `Current User`
uploadstate = `Complete`
trustedsource = abap_true ).
row_derive( CHANGING row = file ).
doc_insert( doc = file after_folders = abap_true ).
rows_build( ).
client->message_toast_display( `Upload completed successfully.` ).
ENDCASE.
ENDMETHOD.
METHOD selection_set.
" onSelectionChange - files and folders are told apart, and Remove All needs
" every item of the open folder selected
t_selected = VALUE #( ).
IF paths IS NOT INITIAL.
SPLIT paths AT `,` INTO TABLE DATA(selected_paths).
LOOP AT selected_paths INTO DATA(path).
DATA(id) = doc_at_path( path ).
IF id IS NOT INITIAL.
INSERT id INTO TABLE t_selected.
ENDIF.
ENDLOOP.
ENDIF.
DATA(files) = 0.
DATA(folders) = 0.
LOOP AT t_selected INTO id.
IF t_docs[ documentid = id ]-isdirectory = abap_true.
folders = folders + 1.
ELSE.
files = files + 1.
ENDIF.
ENDLOOP.
DATA(total) = children_count( current_id ).
removeall_enabled = xsdbool( t_selected IS NOT INITIAL AND lines( t_selected ) = total AND total > 0 ).
IF files > 0 AND folders = 0.
download_enabled = abap_true.
rename_enabled = xsdbool( files = 1 ).
ELSEIF folders > 0 AND files = 0.
download_enabled = abap_false.
rename_enabled = xsdbool( folders = 1 ).
ELSE.
download_enabled = abap_false.
rename_enabled = abap_false.
ENDIF.
ENDMETHOD.
METHOD download.
" onDownloadFiles - one <a download> click per selected file with a URL
DATA(files) = 0.
LOOP AT t_selected INTO DATA(id).
DATA(doc) = t_docs[ documentid = id ].
IF doc-isdirectory = abap_true.
CONTINUE.
ENDIF.
files = files + 1.
IF doc-url IS NOT INITIAL.
client->follow_up_action( val = client->cs_event-download_b64_file
t_arg = VALUE #( ( doc-url ) ( doc-filename ) ) ).
ENDIF.
ENDLOOP.
IF files = 0.
client->message_toast_display( `No files selected for download` ).
RETURN.
ENDIF.
client->message_toast_display( |Download initiated for { files } file(s)| ).
ENDMETHOD.
METHOD folder_create.
" createFolderWithName - into the one selected folder, else the open one
DATA(target) = current_id.
DATA(inside) = ``.
DATA(selected_folders) = 0.
LOOP AT t_selected INTO DATA(id).
IF t_docs[ documentid = id ]-isdirectory = abap_true.
selected_folders = selected_folders + 1.
target = id.
ENDIF.
ENDLOOP.
IF selected_folders = 1.
inside = t_docs[ documentid = target ]-filename.
ELSE.
target = current_id.
ENDIF.
IF line_exists( t_docs[ parentid = target filename = name ] ).
client->message_toast_display( `A folder with this name already exists` ).
RETURN.
ENDIF.
new_no = new_no + 1.
DATA(folder) = VALUE ty_s_doc( parentid = target
documentid = |folder-new-{ new_no }|
filename = name
isdirectory = abap_true
uploadeddate = |{ sy-datum DATE = ISO }|
uploadedby = `Current User`
status = `Active`
documenttype = `Folder`
color = `#ffffff`
bgcolor = `#30914c`
uploadstate = `Complete` ).
row_derive( CHANGING row = folder ).
doc_insert( doc = folder after_folders = abap_false ).
rows_build( ).
IF selected_folders = 1.
client->message_toast_display( |New folder created inside '{ inside }': { name }| ).
ELSE.
client->message_toast_display( |New folder created: { name }| ).
ENDIF.
ENDMETHOD.
METHOD folder_open.
" bindTableItems on the folder's items, the Breadcrumbs history up to its
" parent and the folder as the current location; initial is the root
current_id = id.
t_history = VALUE #( ).
IF id IS INITIAL.
currentlocationtext = `Attachments`.
ELSE.
currentlocationtext = t_docs[ documentid = id ]-filename.
DATA(parent) = t_docs[ documentid = id ]-parentid.
WHILE parent IS NOT INITIAL.
INSERT VALUE #( name = t_docs[ documentid = parent ]-filename path = parent ) INTO t_history INDEX 1.
parent = t_docs[ documentid = parent ]-parentid.
ENDWHILE.
INSERT VALUE #( name = `Attachments` ) INTO t_history INDEX 1.
ENDIF.
rows_build( ).
" the rebound rows start without a selection
t_selected = VALUE #( ).
download_enabled = abap_false.
rename_enabled = abap_false.
removeall_enabled = abap_false.
client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `table-uploadSet` ) ( `clearSelection` ) ) ).
ENDMETHOD.
METHOD remove_all_ask.
" onRemoveAllHandler - only when every item of the open folder is selected
IF t_selected IS INITIAL.
client->message_toast_display( `Please select items to delete` ).
RETURN.
ENDIF.
IF lines( t_selected ) <> children_count( current_id ).
client->message_toast_display( `Please select all items to use Remove All` ).
RETURN.
ENDIF.
client->message_box_display( text = |Are you sure you want to delete ALL { lines( t_selected ) } item(s) in this folder?|
type = `confirm`
title = `Delete All Items`
onclose = `REMOVE_ALL_CLOSE` ).
ENDMETHOD.
METHOD remove_selected.
" deleteAllSelectedItems - files and folders of the open folder
DATA(deleted) = 0.
LOOP AT t_selected INTO DATA(id).
IF line_exists( t_docs[ documentid = id parentid = current_id ] ).
doc_delete( id ).
deleted = deleted + 1.
ENDIF.
ENDLOOP.
IF deleted = 0.
client->message_toast_display( `No items were found to delete` ).
RETURN.
ENDIF.
t_selected = VALUE #( ).
rows_build( ).
client->message_toast_display( |{ deleted } item(s) deleted successfully| ).
ENDMETHOD.
METHOD rows_build.
" the open folder's subtree as the TreeTable's rows
t_items = VALUE #( ).
LOOP AT t_docs INTO DATA(doc1) WHERE parentid = current_id.
DATA(level1) = CORRESPONDING ty_s_level1( doc1 ).
LOOP AT t_docs INTO DATA(doc2) WHERE parentid = doc1-documentid.
DATA(level2) = CORRESPONDING ty_s_level2( doc2 ).
LOOP AT t_docs INTO DATA(doc3) WHERE parentid = doc2-documentid.
DATA(level3) = CORRESPONDING ty_s_level3( doc3 ).
LOOP AT t_docs INTO DATA(doc4) WHERE parentid = doc3-documentid.
INSERT CORRESPONDING ty_s_level4( doc4 ) INTO TABLE level3-items.
ENDLOOP.
INSERT level3 INTO TABLE level2-items.
ENDLOOP.
INSERT level2 INTO TABLE level1-items.
ENDLOOP.
INSERT level1 INTO TABLE t_items.
ENDLOOP.
ENDMETHOD.
METHOD children_count.
LOOP AT t_docs TRANSPORTING NO FIELDS WHERE parentid = parent.
result = result + 1.
ENDLOOP.
ENDMETHOD.
METHOD doc_at_path.
" a row's binding path holds its position on every level below the open
" folder: /T_ITEMS/0/ITEMS/1 is the 2nd child of its 1st item
DATA(parent) = current_id.
DATA(levels) = path_indices( path ).
LOOP AT levels INTO DATA(index).
result = ``.
DATA(position) = 0.
LOOP AT t_docs INTO DATA(doc) WHERE parentid = parent.
position = position + 1.
IF position = index.
result = doc-documentid.
EXIT.
ENDIF.
ENDLOOP.
IF result IS INITIAL.
RETURN.
ENDIF.
parent = result.
ENDLOOP.
ENDMETHOD.
METHOD doc_delete.
" the node and, below a folder, everything in it
LOOP AT t_docs INTO DATA(child) WHERE parentid = id.
doc_delete( child-documentid ).
ENDLOOP.
DELETE t_docs WHERE documentid = id.
ENDMETHOD.
METHOD doc_insert.
" unshift into the parent's items - or, for an uploaded file, in front of
" its first file (behind the folders)
LOOP AT t_docs INTO DATA(sibling) WHERE parentid = doc-parentid.
IF after_folders = abap_false OR sibling-isdirectory = abap_false.
INSERT doc INTO t_docs INDEX sy-tabix.
RETURN.
ENDIF.
ENDLOOP.
INSERT doc INTO TABLE t_docs.
ENDMETHOD.
The first 900 lines of 1077 — the whole class is on GitHub.
More in sap.m
- Plugin for Grid Table (sap.ui.table.Table) — This example demonstrates the usage of UploadSetwithTable plugin for grid table with the…
- Plugin for Responsive Table (sap.m.Table) - Multiple plugin instances with multiple tables — This example demonstrates the usage of multiple plugin instances with multiple tables. Th…
- Plugin for Responsive Table (sap.m.Table) - File upload with user dialogs — This example demonstrates usage of itemValidationHandler callback to leverage additional…
- Plugin for Responsive Table (sap.m.Table) - File Preview — This example showcases how uploaded files can be previewed with FilePreviewDialog control…
- Plugin for Responsive Table (sap.m.Table) - Upload Progress and Upload Termination — This example demonstrates the progress or termination of the items that are being uploade…
- Plugin for Responsive Table (sap.m.Table) — This example demonstrates the usage of UploadSetwithTable plugin for responsive table wit…
- Plugin for Tree Table (sap.ui.table.TreeTable) — This example demonstrates the usage of UploadSetwithTable plugin for tree table with the…
- Manage Products — Created with the 'Worklist App' tutorial. - the UI5 demo app "Manage Products", rebuilt a…
- Browse Orders — Master-detail app for browsing orders. - the UI5 demo app "Browse Orders", rebuilt as one…
- Team Calendar — Calendar demo app for team and team members. - the UI5 demo app "Team Calendar", rebuilt…
- Shopping Cart — The classic business process of finding and ordering products. - the UI5 demo app "Shoppi…
- Bulletin Board — Worklist app created with the 'Testing' tutorial. - the UI5 demo app "Bulletin Board", re…