.po
12 | source_file = i18n/code/source.pot
13 | source_lang = en
14 | type = PO
15 |
--------------------------------------------------------------------------------
/templates/client/html/locale/select/body.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 | = $this->get( 'body' ) ?>
15 |
16 |
17 |
--------------------------------------------------------------------------------
/themes/client/html/default/basket-related.css:
--------------------------------------------------------------------------------
1 | /* Related products to basket */
2 |
3 | .basket-related {
4 | margin: 2rem 0;
5 | }
6 |
7 | .basket-related-bought .header {
8 | border-bottom: 1px solid var(--ai-secondary);
9 | text-transform: uppercase;
10 | text-align: start;
11 | font-weight: normal;
12 | padding: 0.5rem 1rem;
13 | color: var(--ai-secondary);
14 | }
15 |
16 | .basket-related h1 {
17 | display: none;
18 | }
19 |
--------------------------------------------------------------------------------
/manifest.php:
--------------------------------------------------------------------------------
1 | 'ai-client-html',
5 | 'depends' => [
6 | 'aimeos-core',
7 | 'ai-controller-frontend',
8 | ],
9 | 'include' => [
10 | 'src',
11 | ],
12 | 'i18n' => [
13 | 'client' => 'i18n',
14 | 'client/code' => 'i18n/code',
15 | ],
16 | 'config' => [
17 | 'config',
18 | ],
19 | 'template' => [
20 | 'client/html/templates' => [
21 | 'templates/client/html',
22 | ],
23 | ],
24 | ];
25 |
--------------------------------------------------------------------------------
/templates/client/html/checkout/update/header.php:
--------------------------------------------------------------------------------
1 | response()->getStatusCode() . ' ' . $this->response()->getReasonPhrase() );
9 |
10 | foreach( $this->response()->getHeaders() as $key => $value )
11 | {
12 | foreach( (array) $value as $val ) {
13 | @header( $key . ': ' . $val );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/templates/client/html/common/partials/badges.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 | = $enc->html( $this->translate( 'client', 'New' ) ) ?>
14 | = $enc->html( $this->translate( 'client', 'Sale' ) ) ?>
15 |
16 |
--------------------------------------------------------------------------------
/templates/client/html/catalog/session/body.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 | = $this->block()->get( 'catalog/session/pinned' ) ?>
15 | = $this->block()->get( 'catalog/session/seen' ) ?>
16 |
17 |
18 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Base/
6 |
7 |
8 | Client/
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/Client/Html/Exception.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/templates/client/html/catalog/filter/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 | ?>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/templates/client/html/catalog/stage/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/templates/client/html/locale/select/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/templates/client/html/account/profile/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/templates/client/html/account/review/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/templates/client/html/basket/related/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/templates/client/html/catalog/session/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Client/Html/Common/Client/Factory/Base.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/templates/client/html/basket/mini/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
15 | = $this->get( 'miniHeader' ) ?>
16 |
--------------------------------------------------------------------------------
/templates/client/html/account/watch/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/themes/client/html/default/catalog-stage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Catalog session client actions
3 | */
4 | AimeosCatalogStage = {
5 |
6 | /**
7 | * Back to last page
8 | */
9 | onBack() {
10 |
11 | $("body").on("click", ".catalog-stage-breadcrumb a.back", ev => {
12 |
13 | history.back();
14 | return false;
15 | });
16 | },
17 |
18 |
19 | /**
20 | * Initializes the catalog session actions
21 | */
22 | init: function() {
23 | if(this.once) return;
24 | this.once = true;
25 |
26 | this.onBack();
27 | }
28 | };
29 |
30 |
31 | $(function() {
32 | AimeosCatalogStage.init();
33 | });
--------------------------------------------------------------------------------
/themes/client/html/default/checkout-confirm.css:
--------------------------------------------------------------------------------
1 | .checkout-confirm {
2 | padding: 2rem 0;
3 | }
4 |
5 | .checkout-confirm-basic {
6 | padding: 2rem 0;
7 | margin-top: 1.5rem;
8 | }
9 |
10 | .checkout-confirm-basic .attr-list {
11 | padding: 0.5rem 1rem;
12 | margin: 0.5rem;
13 | }
14 |
15 | .checkout-confirm-basic .attr-list .name,
16 | .checkout-confirm-basic .attr-list .value {
17 | display: inline-block;
18 | width: 25%;
19 | }
20 |
21 | .checkout-confirm-basic h2 {
22 | border-bottom: 1px solid var(--ai-secondary);
23 | padding: 0.5rem 1rem;
24 | margin: 0.5rem;
25 | margin-top: 0;
26 | }
27 |
--------------------------------------------------------------------------------
/templates/client/html/account/favorite/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tests/Client/Html/Common/Decorator/Example.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/templates/client/html/account/history/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/tests/phpunit-coverage.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ../src
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Base/
16 |
17 |
18 | Client/
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/Client/Html/Common/Client/Factory/Iface.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 |
13 |
14 |
15 | itemsStockUrl ) ) : ?>
16 | itemsStockUrl as $url ) : ?>
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Base/View/Helper/Attrname/Iface.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 | get( 'errors', [] ) ) ) : ?>
13 |
14 |
15 |
16 | - = $enc->html( $error ) ?>
17 |
18 |
19 |
20 |
21 | get( 'infos', [] ) ) ) : ?>
22 |
23 |
24 |
25 | - = $enc->html( $error ) ?>
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tests/Client/Html/Catalog/Count/Supplier/StandardTest.php:
--------------------------------------------------------------------------------
1 | object = new \Aimeos\Client\Html\Catalog\Count\Supplier\Standard( \TestHelper::context() );
20 | }
21 |
22 |
23 | protected function tearDown() : void
24 | {
25 | unset( $this->object );
26 | }
27 |
28 |
29 | public function testBody()
30 | {
31 | $this->object->setView( $this->object->data( \TestHelper::view() ) );
32 | $output = $this->object->body();
33 |
34 | $this->assertStringStartsWith( '{"', $output );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Client/Html/Common/Decorator/Iface.php:
--------------------------------------------------------------------------------
1 | object = new \Aimeos\Client\Html\Catalog\Count\Attribute\Standard( \TestHelper::context() );
20 | }
21 |
22 |
23 | protected function tearDown() : void
24 | {
25 | unset( $this->object );
26 | }
27 |
28 |
29 | public function testBody()
30 | {
31 | $this->object->setView( $this->object->data( \TestHelper::view() ) );
32 | $output = $this->object->body();
33 |
34 | $this->assertStringStartsWith( '{"', $output );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/themes/client/html/default/account-basket.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Account basket actions
3 | */
4 | AimeosAccountBasket = {
5 |
6 | /**
7 | * Shows basket details without page reload
8 | */
9 | onToggleDetail() {
10 |
11 | $(".account-basket").on("click", ".basket-item .action .btn", ev => {
12 |
13 | const target = $(ev.currentTarget).closest(".basket-item");
14 | const details = $(".account-basket-detail", target);
15 |
16 | $(".btn.show", target).toggleClass('hidden');
17 | $(".btn.close", target).toggleClass('hidden');
18 |
19 | slideToggle(details[0], 300);
20 |
21 | return false;
22 | });
23 | },
24 |
25 |
26 | /**
27 | * Initializes the account basket actions
28 | */
29 | init() {
30 | if(this.once) return;
31 | this.once = true;
32 |
33 | this.onToggleDetail();
34 | }
35 | };
36 |
37 |
38 | $(() => {
39 | AimeosAccountBasket.init();
40 | });
--------------------------------------------------------------------------------
/themes/client/html/default/account-history.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Account history actions
3 | */
4 | AimeosAccountHistory = {
5 |
6 | /**
7 | * Shows history details without page reload
8 | */
9 | onToggleDetail() {
10 |
11 | $(".account-history").on("click", ".history-item .action .btn", ev => {
12 |
13 | const target = $(ev.currentTarget).closest(".history-item");
14 | const details = $(".account-history-detail", target);
15 |
16 | $(".btn.show", target).toggleClass('hidden');
17 | $(".btn.close", target).toggleClass('hidden');
18 |
19 | slideToggle(details[0], 300);
20 |
21 | return false;
22 | });
23 | },
24 |
25 |
26 | /**
27 | * Initializes the account history actions
28 | */
29 | init() {
30 | if(this.once) return;
31 | this.once = true;
32 |
33 | this.onToggleDetail();
34 | }
35 | };
36 |
37 |
38 | $(() => {
39 | AimeosAccountHistory.init();
40 | });
--------------------------------------------------------------------------------
/templates/client/html/basket/standard/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 | = $this->translate( 'client', 'Basket' ) ?> | = $enc->html( $this->get( 'contextSiteLabel', 'Aimeos' ) ) ?>
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tests/Client/Html/Catalog/Count/Tree/StandardTest.php:
--------------------------------------------------------------------------------
1 | object = new \Aimeos\Client\Html\Catalog\Count\Tree\Standard( \TestHelper::context() );
20 | $this->object->setView( \TestHelper::view() );
21 | }
22 |
23 |
24 | protected function tearDown() : void
25 | {
26 | unset( $this->object );
27 | }
28 |
29 |
30 | public function testBody()
31 | {
32 | $this->object->setView( $this->object->data( \TestHelper::view() ) );
33 | $output = $this->object->body();
34 |
35 | $this->assertStringStartsWith( '{"', $output );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Base/View/Helper/Image/Iface.php:
--------------------------------------------------------------------------------
1 | {
12 |
13 | const target = $(ev.currentTarget).closest(".subscription-item");
14 | const details = $(".account-subscription-detail", target);
15 |
16 | $(".btn.show", target).toggleClass('hidden');
17 | $(".btn.close", target).toggleClass('hidden');
18 |
19 | slideToggle(details[0], 300);
20 |
21 | return false;
22 | });
23 | },
24 |
25 |
26 | /**
27 | * Initializes the account subscription actions
28 | */
29 | init() {
30 | if(this.once) return;
31 | this.once = true;
32 |
33 | this.onToggleDetail();
34 | }
35 | };
36 |
37 |
38 | $(() => {
39 | AimeosAccountSubscription.init();
40 | });
--------------------------------------------------------------------------------
/templates/client/html/catalog/detail/navigator.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 | ?>
11 | param( 'd_pos' ) !== null ) : ?>
12 |
29 |
30 |
--------------------------------------------------------------------------------
/templates/client/html/checkout/confirm/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 | = $this->translate( 'client', 'Confirmation' ) ?> | = $enc->html( $this->get( 'contextSiteLabel', 'Aimeos' ) ) ?>
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/templates/client/html/checkout/standard/header.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 | = $this->translate( 'client', $this->get( 'standardStepActive' ) ) ?> | = $enc->html( $this->get( 'contextSiteLabel', 'Aimeos' ) ) ?>
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Aimeos HTML client
6 |
7 | [](https://circleci.com/gh/aimeos/ai-client-html)
8 | [](https://coveralls.io/r/aimeos/ai-client-html?branch=master)
9 | [](https://scrutinizer-ci.com/g/aimeos/ai-client-html/?branch=master)
10 | [](https://packagist.org/packages/aimeos/ai-client-html)
11 |
12 | Aimeos HTML components for e-commerce projects
13 |
14 | [](http://demo.aimeos.org/)
15 |
16 |
--------------------------------------------------------------------------------
/themes/client/html/default/account-review.css:
--------------------------------------------------------------------------------
1 | .account-review {
2 | padding: 2rem 0;
3 | }
4 |
5 | .account-review .header {
6 | text-transform: uppercase;
7 | text-align: start;
8 | font-weight: normal;
9 | padding: 0.5rem 1rem;
10 | color: var(--ai-secondary);
11 | border-bottom: 1px solid var(--ai-secondary);
12 | }
13 |
14 | .account-review .review-item {
15 | padding: 1rem;
16 | }
17 |
18 | .account-review .col-md-6 {
19 | padding-top: 1rem;
20 | }
21 |
22 | .account-review .review-image {
23 | max-width: 100%;
24 | max-height: 10rem;
25 | }
26 |
27 | .account-review .review-rating input {
28 | vertical-align: middle;
29 | }
30 |
31 | .account-review .review-rating input:checked ~ label {
32 | color: var(--ai-primary);
33 | }
34 |
35 | .account-review .review-comment {
36 | width: 100%;
37 | height: 8.5rem;
38 | padding: 0.5rem;
39 | border: 1px solid var(--ai-tertiary);
40 | }
41 |
42 | .account-review .btn {
43 | display: block;
44 | margin: 1rem auto;
45 | }
46 |
--------------------------------------------------------------------------------
/themes/client/html/default/account-favorite.css:
--------------------------------------------------------------------------------
1 | .account-favorite {
2 | padding: 2rem 0;
3 | }
4 |
5 | .account-favorite .header {
6 | text-transform: uppercase;
7 | text-align: start;
8 | font-weight: normal;
9 | padding: 0.5rem 1rem;
10 | color: var(--ai-secondary);
11 | border-bottom: 1px solid var(--ai-secondary);
12 | }
13 |
14 | .account-favorite .favorite-items {
15 | display: flex;
16 | justify-content: center;
17 | }
18 |
19 | .account-favorite .favorite-item {
20 | position: relative;
21 | text-align: end;
22 | width: 180px;
23 | margin: 1%;
24 | }
25 |
26 | .account-favorite .name {
27 | margin-top: 0.75rem;
28 | }
29 |
30 | .account-favorite .price-list .rebatepercent {
31 | display: none;
32 | }
33 |
34 | .account-favorite form.delete {
35 | position: absolute;
36 | left: 0;
37 | top: 0;
38 | }
39 |
40 | .account-favorite .minibutton.delete {
41 | color: var(--ai-secondary);
42 | background-color: var(--ai-bg);
43 | padding: .5rem 0.75rem;
44 | z-index: 5;
45 | }
46 |
47 | .account-favorite .media-item > img {
48 | width: 100%;
49 | }
50 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aimeos/ai-client-html",
3 | "description": "Aimeos standard HTML frontend",
4 | "keywords": ["aimeos", "extension", "client", "html"],
5 | "homepage": "https://aimeos.org/",
6 | "type": "aimeos-extension",
7 | "license": "LGPL-3.0-or-later",
8 | "support": {
9 | "source": "https://github.com/aimeos/ai-client-html",
10 | "issues": "https://github.com/aimeos/ai-client-html/issues",
11 | "forum": "https://aimeos.org/help",
12 | "wiki": "https://aimeos.org/docs"
13 | },
14 | "prefer-stable": true,
15 | "minimum-stability": "dev",
16 | "require": {
17 | "php": "^8.0.11",
18 | "aimeos/aimeos-core": "dev-master",
19 | "aimeos/ai-controller-frontend": "dev-master"
20 | },
21 | "require-dev": {
22 | "phpunit/phpunit": "~10.0||~11.0",
23 | "nyholm/psr7-server": "~1.0"
24 | },
25 | "autoload": {
26 | "psr-4": {
27 | "Aimeos\\": "src"
28 | },
29 | "classmap": [
30 | "src"
31 | ]
32 | },
33 | "autoload-dev": {
34 | "psr-4": {
35 | "Aimeos\\": "tests"
36 | },
37 | "classmap": [
38 | "tests"
39 | ]
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/templates/client/html/basket/related/body.php:
--------------------------------------------------------------------------------
1 | encoder();
9 |
10 |
11 | ?>
12 | get( 'boughtItems', map() )->isEmpty() ) : ?>
13 |
14 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/tests/Client/Html/Catalog/Filter/Search/StandardTest.php:
--------------------------------------------------------------------------------
1 | object = new \Aimeos\Client\Html\Catalog\Filter\Search\Standard( \TestHelper::context() );
24 | $this->object->setView( \TestHelper::view() );
25 | }
26 |
27 |
28 | protected function tearDown() : void
29 | {
30 | \Aimeos\Controller\Frontend::cache( false );
31 | \Aimeos\MShop::cache( false );
32 |
33 | unset( $this->object );
34 | }
35 |
36 |
37 | public function testBody()
38 | {
39 | $output = $this->object->body();
40 | $this->assertStringStartsWith( ' {
12 |
13 | const form = $(ev.currentTarget).closest("form");
14 | $(ev.currentTarget).closest("favorite-item").addClass("loading");
15 |
16 | await fetch(form.attr("action"), {
17 | body: new FormData(form[0]),
18 | method: 'POST'
19 | }).then(response => {
20 | return response.text();
21 | }).then(data => {
22 | const doc = $("
").html(data);
23 |
24 | $(".aimeos.account-favorite").replaceWith($(".aimeos.account-favorite", doc));
25 |
26 | if(!$(".aimeos.account-favorite .favorite-items").length) {
27 | Aimeos.removeOverlay();
28 | }
29 | });
30 |
31 | return false;
32 | });
33 | },
34 |
35 |
36 | /**
37 | * Initializes the account favorite actions
38 | */
39 | init() {
40 | if(this.once) return;
41 | this.once = true;
42 |
43 | this.onRemoveProduct();
44 | }
45 | };
46 |
47 |
48 | $(function() {
49 | AimeosAccountFavorite.init();
50 | });
--------------------------------------------------------------------------------
/tests/Client/Html/Catalog/Filter/Price/StandardTest.php:
--------------------------------------------------------------------------------
1 | view = \TestHelper::view();
25 | $this->context = \TestHelper::context();
26 |
27 | $this->object = new \Aimeos\Client\Html\Catalog\Filter\Price\Standard( $this->context );
28 | $this->object->setView( $this->view );
29 | }
30 |
31 |
32 | protected function tearDown() : void
33 | {
34 | \Aimeos\Controller\Frontend::cache( false );
35 | \Aimeos\MShop::cache( false );
36 |
37 | unset( $this->object, $this->context, $this->view );
38 | }
39 |
40 |
41 | public function testBody()
42 | {
43 | $this->view->priceHigh = 100;
44 | $output = $this->object->body();
45 | $this->assertStringStartsWith( '
79 |
80 |
81 |
--------------------------------------------------------------------------------
/tests/Client/Html/Catalog/Product/StandardTest.php:
--------------------------------------------------------------------------------
1 | view = \TestHelper::view();
25 | $this->context = \TestHelper::context();
26 | $this->context->config()->set( 'client/html/catalog/product/product-codes', ['CNE', 'ABCD', 'CNC'] );
27 |
28 | $this->object = new \Aimeos\Client\Html\Catalog\Product\Standard( $this->context );
29 | $this->object->setView( $this->view );
30 | }
31 |
32 |
33 | protected function tearDown() : void
34 | {
35 | \Aimeos\Controller\Frontend::cache( false );
36 | \Aimeos\MShop::cache( false );
37 |
38 | unset( $this->object, $this->context, $this->view );
39 | }
40 |
41 |
42 | public function testHeader()
43 | {
44 |
45 | $manager = \Aimeos\MShop::create( $this->context, 'product' );
46 | $filter = $manager->filter()->add( ['product.code' => ['CNE', 'ABCD', 'CNC']] );
47 | $map = $manager->search( $filter )->col( 'product.id', 'product.code' );
48 |
49 | $tags = [];
50 | $expire = null;
51 |
52 | $this->object->setView( $this->object->data( $this->view, $tags, $expire ) );
53 | $output = $this->object->header();
54 |
55 | $this->assertStringContainsString( '