diff --git a/src/components/main.js b/src/components/main.js index a39521d9654812a7e5c99de1f029775e54a9b034..519f2053edb764e207217e69f21479832034d3bc 100644 --- a/src/components/main.js +++ b/src/components/main.js @@ -533,129 +533,115 @@ import("@helpers/utils.js").then((utils) => { >Learn more about us</a > </div> - <hr /> - <div class="row"> - <div class="col s6"> - <div class="row no-margin-bottom"> - <div class="col s12"> - <span class="bold-16-21" - >Assurance Partners</span - > + <!-- Commented: Missing information on how ecological outcomes should work --> + <conditional-display + bind-resources="" + condition="ofn:hasSupportingEvidence"> + <hr /> + <div class="row"> + <!-- <div class="col s6"> + <div class="row no-margin-bottom"> + <div class="col s12"> + <span class="bold-16-21" + >Assurance Partners</span + > + </div> </div> - </div> - <div class="row"> - <div class="col s12"> - <a - class="learn-more underline" - href="#${this.uniq}-supporting-evidence" - >Learn more</a - > + <div class="row"> + <div class="col s12"> + <a + class="learn-more underline" + href="#${this.uniq}-supporting-evidence" + >Learn more</a + > + </div> </div> - </div> - <div class="row"> - <div class="col s12"> - <solid-display - bind-resources="" - nested-field="ofn:hasSupportingEvidence" - fields="ofn:promo_image_url, ofn:Title" - widget-ofn:promo_image_url="solid-display-img" - class-ofn:Title="text-14 text-green bold underline" - ></solid-display> + <div class="row"> + <div class="col s12"> + <solid-display + bind-resources="" + nested-field="ofn:hasSupportingEvidence" + fields="ofn:promo_image_url, ofn:Title" + widget-ofn:promo_image_url="solid-display-img" + class-ofn:Title="text-14 text-green bold underline" + ></solid-display> + </div> </div> - </div> - </div> - <!-- Commented: Missing information on how ecological outcomes should work --> - <!-- <div class="col s6"> - <div class="row"> - <div class="col s12"> - <span class="bold-16-21" - >Supporting Evidence</span - > + </div> --> + <div class="col s6"> + <div class="row"> + <div class="col s12"> + <span class="bold-16-21" + >Supporting Evidence</span + > + </div> </div> - </div> - <div class="row"> - <div class="col s12"> - <a - class="learn-more underline" - href="#${this.uniq}-supporting-evidence" - >Learn more</a - > - </div> - </div> - <div class="row no-margin-bottom"> - <div class="col s12"> - <div class="chip small text-12 peach">1</div> - <span class="text-14 text-light"> - for - <span class="underline" - >ecological outcomes</span - ></span - > - </div> - </div> - <div class="row no-margin-bottom"> - <div class="col s12"> - <div class="chip small text-12 peach">2</div> - <span class="text-14 text-light"> - for - <span class="underline" - >practices</span - ></span - > + <div class="row"> + <div class="col s12"> + <a + class="learn-more underline" + href="#${this.uniq}-supporting-evidence" + >Learn more</a + > + </div> </div> + <!-- <div class="row no-margin-bottom"> + <div class="col s12"> + <div class="chip small text-12 peach">1</div> + <span class="text-14 text-light"> + for + <span class="underline" + >ecological outcomes</span + ></span + > + </div> + </div> --> </div> - <div class="row no-margin-bottom"> - <div class="col s12"> - <div class="chip small text-12 peach">1</div> - <span class="text-14 text-light"> - for - <span class="underline" - >participation</span - ></span - > - </div> - </div> - </div> --> - </div> + </div> + </conditional-display> </div> </div> </div> </div> </div> - <h4 id="${this.uniq}-how-to-buy">How to buy</h4> - <div class="row"> - <div class="col s12"> - <div class="card-panel card-round card-padding"> - <div class="row"> - <div class="col s3"> - <custom-wholesale-buy bind-resources="" uniq="${this.uniq}"></custom-wholesale-buy> - </div> - <div class="col s8 offset-s1"> - <h5>Feature products</h5> - <solid-display - bind-resources="" - nested-field="dfc-b:supplies" - fields="set-card-col(set-card-panel(set-card-wrapper(set-image(ofn:image), set-name(dfc-b:name))))" - widget-set-card-row="div" - class-set-card-row="row" - widget-set-card-col="div" - class-set-card-col="col s6 m4" - widget-set-card-panel="div" - class-set-card-panel="card-panel" - widget-set-card-wrapper="div" - class-ofn:image="img-200" - widget-ofn:image="solid-display-img" - default-ofn:image="https://placehold.co/200" - widget-set-name="div" - class-set-name="row no-margin-bottom" - widget-dfc-b:name="solid-display-value" - class-dfc-b:name="col s12 truncate" - ></solid-display> + <conditional-display + bind-resources="" + condition="dfc-b:supplies"> + <h4 id="${this.uniq}-how-to-buy">How to buy</h4> + <div class="row"> + <div class="col s12"> + <div class="card-panel card-round card-padding"> + <div class="row"> + <div class="col s3"> + <custom-wholesale-buy bind-resources="" uniq="${this.uniq}"></custom-wholesale-buy> + </div> + <div class="col s8 offset-s1"> + <h5>Feature products</h5> + <solid-display + bind-resources="" + nested-field="dfc-b:supplies" + fields="set-card-col(set-card-panel(set-card-wrapper(set-image(ofn:image), set-name(dfc-b:name))))" + widget-set-card-row="div" + class-set-card-row="row" + widget-set-card-col="div" + class-set-card-col="col s6 m4" + widget-set-card-panel="div" + class-set-card-panel="card-panel" + widget-set-card-wrapper="div" + class-ofn:image="img-200" + widget-ofn:image="solid-display-img" + default-ofn:image="https://placehold.co/200" + widget-set-name="div" + class-set-name="row no-margin-bottom" + widget-dfc-b:name="solid-display-value" + class-dfc-b:name="col s12 truncate" + ></solid-display> + </div> </div> </div> </div> </div> - </div> + </conditional-display> <h4 id="${this.uniq}-about-us">About us</h4> <div class="row"> <div class="col s12"> @@ -734,17 +720,41 @@ import("@helpers/utils.js").then((utils) => { </div> </div> </div> - <h4 id="${this.uniq}-supporting-evidence"> - Supporting evidence - </h4> - <div class="row"> - <div class="col s12"> - <div class="row"> - <div class="col s3"></div> - <div class="col s8"></div> + <conditional-display + bind-resources="" + condition="ofn:hasSupportingEvidence"> + <h4 id="${this.uniq}-supporting-evidence"> + Supporting evidence + </h4> + <div class="row"> + <div class="col s12"> + <div class="card-panel card-padding"> + <div class="row"> + <div class="col s3"> + <solid-form-search + id="search-supporting-evidence-${this.uniq}" + fields="ofn:Classification" + auto-range-ofn:Classification="" + widget-ofn:Classification="solid-form-checkbox" + option-label-ofn:Classification="ofn:label" + ></solid-form-search> + Coming soon. :) + </div> + <div class="col s8"> + <solid-display + bind-resources="" + nested-field="ofn:hasSupportingEvidence" + fields="virtualid" + value-virtualid="store://resource.@id" + widget-virtualid="custom-supporting-evidence" + filtered-by="search-supporting-evidence-${this.uniq}" + ></solid-display> + </div> + </div> + </div> </div> </div> - </div> + </conditional-display> <custom-contact-form bind-resources="" uniq="${this.uniq}"></custom-contact-form> </div> </div> diff --git a/src/components/partials/conditional-display.js b/src/components/partials/conditional-display.js new file mode 100644 index 0000000000000000000000000000000000000000..06a181ee6bb1039582cfda479e3e481a85655c3b --- /dev/null +++ b/src/components/partials/conditional-display.js @@ -0,0 +1,69 @@ +import { LitElement, html } from "lit"; +import { Task } from "@lit/task"; + +import("@helpers/utils.js").then((utils) => { + import(/* @vite-ignore */ utils.coreVersion()).then((core) => { + // Custom widget for wholesale + customElements.define( + "conditional-display", + class extends LitElement { + constructor() { + super(); + } + + static properties = { + dataSrc: { attribute: "data-src" }, + condition: { attribute: "condition" }, + } + + /** + * Check if a resource exists or if a container isn't empty + * + * @param {Object} resource - The resource to retrieve the property value from + * @param {string} property - The property to retrieve the value for + * @return {boolean} Whether the property value is a proxy value or not + */ + async _getProxyValue(resource, property) { + let response = await resource[property]; + if(response && typeof response === "object" && "getProxy" in response) { + if((await response['properties']).includes("ldp:contains")) { + let container = await response.get("ldp:contains"); + if(container === null) { + return false; + } + return container.length > 0; + } else { + return true; + } + } + return !!response; + } + + _getResource = new Task(this, { + task: async ([dataSrc, property]) => { + if(!dataSrc) return; + const resource = await core.store.getData(dataSrc, utils.CLIENT_CONTEXT); + let response = await this._getProxyValue(resource, property); + return response; + }, + args: () => [this.dataSrc, this.condition] + }) + + render() { + if(!this.dataSrc || !this.condition) return html``; + + return this._getResource.render({ + pending: () => html`<div class="progress"><div class="indeterminate"></div></div>`, + complete: (resource) => { + if(resource) { + return html`<slot></slot>`; + } + return html``; + }, + error: (e) => html`<p>Error while loading condition.</p>` + }); + } + } + ); + }); +}); diff --git a/src/components/partials/contact-form.js b/src/components/partials/contact-form.js index a6a603eb3abddaa41ab50afb0140fc55dc023314..c1af61027d443368ff3bfeca7fe775ff149f2479 100644 --- a/src/components/partials/contact-form.js +++ b/src/components/partials/contact-form.js @@ -28,7 +28,7 @@ import("@helpers/utils.js").then((utils) => { async _getProxyValue(resource) { let response = { "ofn:Wholesale_enquiry_preferences": await resource["ofn:Wholesale_enquiry_preferences"], - "dfc-b:hasPhoneNumber": "Hello, I'm a phone number and my context is wrong.", //await resource["dfc-b:hasPhoneNumber"], + "dfc-b:hasPhoneNumber": await resource["dfc-b:hasPhoneNumber"], "dfc-b:email": await resource["dfc-b:email"], "ofn:contact_email_endpoint_uri": await resource["ofn:contact_email_endpoint_uri"], }; @@ -75,7 +75,6 @@ import("@helpers/utils.js").then((utils) => { return this._getResource.render({ pending: () => html`<div class="progress"><div class="indeterminate"></div></div>`, complete: (resource) => { - console.log(resource); let render = html``; if(resource["ofn:Wholesale_enquiry_preferences"]) { if(resource["ofn:Wholesale_enquiry_preferences"].includes("Email")) { diff --git a/src/components/partials/supporting-evidence.js b/src/components/partials/supporting-evidence.js new file mode 100644 index 0000000000000000000000000000000000000000..77d41c153323496ec76c4f18387b856442617c69 --- /dev/null +++ b/src/components/partials/supporting-evidence.js @@ -0,0 +1,129 @@ +import { LitElement, html } from "lit"; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import { Task } from "@lit/task"; +import '~icons/mdi/file-document-check-outline'; + +import("@helpers/utils.js").then((utils) => { + import(/* @vite-ignore */ utils.coreVersion()).then((core) => { + // Custom widget for supporting evidence + customElements.define( + "custom-supporting-evidence", + class extends LitElement { + constructor() { + super(); + } + + static properties = { + dataSrc: { attribute: "value" }, + } + + createRenderRoot() { + return this; + } + + /** + * Asynchronously gets the proxy value for the given resource. + * + * @param {proxy} resource - description of resource + * @return {object} response containing the serialized resource + */ + async _getProxyValue(resource) { + let response = {}; + for(let property of await resource['properties']) { + let value = resource[property]; + if(!property.startsWith('@')) { + value = await resource.get(property); + try { + if(value && typeof value === "object" && "getProxy" in value) { + value = await this._getProxyValue(value); + } + } catch (e) { + if(import.meta.env.DEV) console.error(e); + } + } + if(property == "ldp:contains") { + try { + // Bug core? When ldp:contains have only one entry, it is not an array + if(!Array.isArray(value) && value !== null) { + value = [value]; + } + let expandedContainer = []; + for(let entry of value) { + // Grab the whole nested datas from the store using the clientContext + entry = await core.store.getData(entry["@id"], resource['clientContext']); + expandedContainer.push(await this._getProxyValue(entry)); + } + // Rewrite the ldp:contains with a complete one + value = expandedContainer; + } catch (e) { + if(import.meta.env.DEV) console.error(e); + } + } + response[property] = value; + } + return response; + } + + _getResource = new Task(this, { + task: async ([dataSrc]) => { + if(!dataSrc) return; + const resource = await core.store.getData(dataSrc, utils.CLIENT_CONTEXT); + let response = await this._getProxyValue(resource); + return response; + }, + args: () => [this.dataSrc] + }) + + /** + * Helper function that adds the given template to the current rendering. + * + * @param {html} template - the template to be added to the rendering + */ + _addToRender(template) { + if(!this.rendering) this.rendering = html``; + this.rendering = html`${this.rendering}${template}`; + } + + render() { + if(!this.dataSrc) return html``; + + return this._getResource.render({ + pending: () => html`<div class="progress"><div class="indeterminate"></div></div>`, + complete: (resource) => { + this.rendering = html``; + + this._addToRender(html` + <div class="text-14 text-light-grey">${resource['ofn:Creation_date']}</div> + <span class="text-18 bold text-black line-height-40 margin-right-10">${resource['ofn:Title']}</span> + `); + + for(let classification of resource['ofn:Classification']['ldp:contains']) { + this._addToRender(html` + <div class="chip white vertical-align-middle">${classification['ofn:label']}</div> + `); + } + + this._addToRender(html` + <!-- <div>Source ${resource['ofn:???']}</div> --> + <div>${unsafeHTML(utils.sanitize(resource['ofn:Description'], false))}</div> + `); + + if(resource['ofn:Documentation_permissions']) { + this._addToRender(html` + <div class="margin-top-20 document-availibility">${resource['ofn:Documentation_permissions'].replace('Available on request', 'Documentation available upon direct request to producer')} <icon-mdi-file-document-check-outline></icon-mdi-file-document-check-outline></div> + `); + } + + return html` + <div class="card-panel card-evidence"> + ${this.rendering} + </div> + `; + }, + error: (e) => html`<p>Error while loading supporting evidence informations.</p>` + }); + } + } + ); + }); +}); diff --git a/src/components/partials/wholesale-buy.js b/src/components/partials/wholesale-buy.js index 8d332596325222af75bafdccfa24149a4554b043..812518e761eaa62657f0a9ed03790b218b86c56c 100644 --- a/src/components/partials/wholesale-buy.js +++ b/src/components/partials/wholesale-buy.js @@ -32,16 +32,14 @@ import("@helpers/utils.js").then((utils) => { let response = {}; for(let property of await resource['properties']) { let value = resource[property]; - if(property == "dfc-b:hasPhoneNumber") { - value = "Hello, I'm a phone number and my context is wrong."; - } else if(!property.startsWith('@')) { + if(!property.startsWith('@')) { value = await resource.get(property); try { if(value && typeof value === "object" && "getProxy" in value) { value = await this._getProxyValue(value); } } catch (e) { - console.error(e); + if(import.meta.env.DEV) console.error(e); } } response[property] = value; diff --git a/src/styles/index.scss b/src/styles/index.scss index b247d70959706efc888e6e1ea43f4ac094bda047..3e339823cc7aec37b15aa57794d2acd093707534 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -65,6 +65,14 @@ solid-ofn-rpp { line-height: 21px; } + .line-height-40 { + line-height: 40px; + } + + .text-black { + color: #191C1D; + } + .loader { margin-top: 30px; padding: 60px; @@ -107,6 +115,10 @@ solid-ofn-rpp { padding-left: 50px; background-position: 12px; } + &.white { + background-color: white; + border: 1px solid black; + } } .dfc_b_name { @@ -249,6 +261,11 @@ solid-ofn-rpp { } } + .card-evidence { + box-shadow: 0px 4px 4px 0px #0000000D !important; + padding: 30px !important; + } + .title-header { overflow: auto; position: relative; @@ -438,7 +455,30 @@ solid-ofn-rpp { custom-multiple-badge[name="ofn:Practices"] .chip { border: 1px solid black; border-radius: 26px; + } + + .text-light-grey { + color: #6F7D81; + } + .vertical-align-middle { + vertical-align: middle; + } + + .document-availibility { + @extend .text-14; + font-weight: 700; + line-height: 24px; + color: #191C1D; + icon-mdi-file-document-check-outline { + vertical-align: text-top; + margin-left: 4px; + font-size: 20px; + svg { + width: 20px; + height: 20px; + } + } } }