aboutsummaryrefslogtreecommitdiffstats
path: root/documentation/components/components-customcomponent.asciidoc
blob: 5adca246c8b68ca63bf506632f6c66be7871e49b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
---
title: Composition with Composite and CustomComponent
order: 33
layout: page
---

[[components.customcomponent]]
= Composition with Composite and CustomComponent

The ease of making new user interface components is one of the core features of
Vaadin. Typically, you simply combine existing built-in components to produce
composite components. In many applications, such composite components make up
the majority of the user interface.

As described earlier in
<<../application/application-architecture#application.architecture.composition,"Compositing
Components">>, you have two basic ways to create a composite - either by
extending a layout component or by using a composition component (a
[classname]#Composite# or a [classname]#CustomComponent#), which typically
wraps around a layout component.
The benefit of wrapping a layout composite is mainly encapsulation - hiding the
implementation details of the composition. Otherwise, a user of the composite
could rely on implementation details, which would create an unwanted dependency.

To create a composite, you need to inherit [classname]#Composite# or
[classname]#CustomComponent# and set the __composition root__ component in the
constructor. The composition root is typically a layout component that contains
other components.

The difference between the two composition classes is that a
[classname]#CustomComponent# introduces another layer in the DOM on the
browser, which can be used e.g. for styling but does require its own size
setting etc. On the other hand, a [classname]#Composite# is a more light-weight
version that has no visual representation in the browser, and is effectively
replaced by its contents.

For example:

[source, java]
----
class MyComposite extends CustomComponent {
    public MyComposite(String message) {
        // A layout structure used for composition
        Panel panel = new Panel("My Custom Component");
        VerticalLayout panelContent = new VerticalLayout();
        panel.setContent(panelContent);

        // Compose from multiple components
        Label label = new Label(message);
        panelContent.addComponent(label);
        panelContent.addComponent(new Button("Ok"));

        // The composition root MUST be set
        setCompositionRoot(panel);

        // Set the size as undefined at all levels
        panelContent.setSizeUndefined();
        panel.setSizeUndefined();
        // this is not needed for a Composite
        setSizeUndefined();
    }
}
----

Take note of the sizing when trying to make a customcomponent that shrinks to
fit the contained components. You have to set the size as undefined at all
levels. In the case of [classname]#CustomComponent#, the sizing of the composite
component and the composition root are separate, whereas [classname]#Composite#
delegates its size management to its composition root.

You can use the component as follows:

[source, java]
----
MyComposite mycomposite = new MyComposite("Hello");
----

The rendered component is shown in <<figure.components.customcomponent>>.

[[figure.components.customcomponent]]
.A custom composite component
image::img/customcomponent-example1.png[width=25%, scaledwidth=40%]

You can also inherit any other components, such as layouts, to attain similar
composition.
((("Google Web Toolkit")))
Even further, you can create entirely new low-level components, by integrating
pure client-side components or by extending the client-side functionality of
built-in components. Development of new components is covered in
<<../gwt/gwt-overview.asciidoc#gwt.overview,"Integrating
with the Server-Side">>.
8/stable30'>backport/46218/stable30 Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
aboutsummaryrefslogtreecommitdiffstats
path: root/public.php
blob: 8ae6deff20305bd7ef33f0f6f2760f26fafe2feb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?php

declare(strict_types=1);

use OC\ServiceUnavailableException;

/**
 * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
 * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
 * SPDX-License-Identifier: AGPL-3.0-only
 */

require_once __DIR__ . '/lib/versioncheck.php';

use OCP\App\IAppManager;
use OCP\IConfig;
use OCP\IRequest;
use OCP\Server;
use OCP\Template\ITemplateManager;
use OCP\Util;
use Psr\Log\LoggerInterface;

function resolveService(string $service): string {
	$services = [
		'webdav' => 'dav/appinfo/v1/publicwebdav.php',
		'dav' => 'dav/appinfo/v2/publicremote.php',
	];
	if (isset($services[$service])) {
		return $services[$service];
	}

	return Server::get(IConfig::class)->getAppValue('core', 'remote_' . $service);
}

try {
	require_once __DIR__ . '/lib/base.php';

	// All resources served via the DAV endpoint should have the strictest possible
	// policy. Exempted from this is the SabreDAV browser plugin which overwrites
	// this policy with a softer one if debug mode is enabled.
	header("Content-Security-Policy: default-src 'none';");

	// Check if Nextcloud is in maintenance mode
	if (Util::needUpgrade()) {
		// since the behavior of apps or remotes are unpredictable during
		// an upgrade, return a 503 directly
		throw new \Exception('Service unavailable', 503);
	}

	$request = Server::get(IRequest::class);
	$pathInfo = $request->getPathInfo();
	if ($pathInfo === false || $pathInfo === '') {
		throw new \Exception('Path not found', 404);
	}

	// Extract the service from the path
	if (!$pos = strpos($pathInfo, '/', 1)) {
		$pos = strlen($pathInfo);
	}
	$service = substr($pathInfo, 1, $pos - 1);

	// Resolve the service to a file
	$file = resolveService($service);
	if (!$file) {
		throw new \Exception('Path not found', 404);
	}

	// Extract the app from the service file
	$file = ltrim($file, '/');
	$parts = explode('/', $file, 2);
	$app = $parts[0];

	// Load all required applications
	$appManager = Server::get(IAppManager::class);
	\OC::$REQUESTEDAPP = $app;
	$appManager->loadApps(['authentication']);
	$appManager->loadApps(['extended_authentication']);
	$appManager->loadApps(['filesystem', 'logging']);

	// Check if the app is enabled
	if (!$appManager->isEnabledForUser($app)) {
		throw new \Exception('App not installed: ' . $app);
	}

	// Load the app
	$appManager->loadApp($app);
	OC_User::setIncognitoMode(true);

	$baseuri = OC::$WEBROOT . '/public.php/' . $service . '/';
	require_once $file;
} catch (Exception $ex) {
	$status = 500;
	if ($ex instanceof ServiceUnavailableException) {
		$status = 503;
	}
	//show the user a detailed error page
	Server::get(LoggerInterface::class)->error($ex->getMessage(), ['app' => 'public', 'exception' => $ex]);
	Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, $status);
} catch (Error $ex) {
	//show the user a detailed error page
	Server::get(LoggerInterface::class)->error($ex->getMessage(), ['app' => 'public', 'exception' => $ex]);
	Server::get(ITemplateManager::class)->printExceptionErrorPage($ex, 500);
}