mercredi 30 juin 2021

How could I set the class property passed as an array to an inner rendered component for ember test as at the moment by using set doesnt pass array?

the users are defined on the component class

// recipients-component.js
export default class RecipientsComponent extends Component {

get users () {
return [{name:'jerry'},{name:'ana'},{name:'erik'}]
}

get selectedUsers () {
return [{name:'jerry'}]
}

}

This users are passed to a powerSlectMultiple component


// recipients-component.hbs
  <div class="card-row">
 <h3>Recipients</>
        <div class="card-row">
          <PowerSelectMultiple
        @placeholder="Select recipient(s)"
        @searchEnabled=true
        @selected=
        @options=
        @onChange=
        @onKeydown=
        @searchField="name"
        as |user|
      >
        
      </PowerSelectMultiple>
  </div>

Not rendering the users array when I create those with this.set()

  • Is there a way to pass or create the users array to pass into this component?

// recipients-component-test.js
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Component | recipients-component', function (hooks) {
  setupRenderingTest(hooks);

  test('it renders users', function (assert) {

   this.set('users', [{name:'jerry'},{name:'ana'},{name:'erik'}]); // not working
   await render(hbs`<Recipients-component  />`);

    assert.equal(this.$('h3').text().trim(), 'Recipients');
  });
});



mardi 29 juin 2021

Best approach to caching in Ember Octane

I have a project running Ember@3.20. We are currently in the process of migrating from classic to glimmer based components and have come across some expensive computational patterns which would benefit from caching.

My question is, what is the best approach to caching functionality to getters for glimmer components? It looks like there are currently a few ways to do this:

  1. @cached via tracked-toolbox - I believe this was released prior to the ember cached api. I didn't peek under the hood but it has the has a @cached decorator which might collide with future ember @cached.
  2. ember-cache-primitive-polyfill - Mentioned in the Ember docs as a polyfill for the ember cached API (3.22) but the syntax isn't as concise as the @cached decorator
  3. ember-cached-decorator-polyfill - related to RFC566 appears to be based on option 2 with a more ergonomic syntax
  4. Upgrade to 3.22 - Trying to avoid bumping ember unless there is a significant benefit. At a glance, I didn't see @cached included here though.

Any additional insight/guidelines into how expensive a getter should be to warrant it being cached? For example, preventing re-renders seems a fairly obvious use case but there can be a wide range of what developers might consider an "expensive" computation.




mercredi 23 juin 2021

Serving image assets from S3 in Ember app

I have a Rails server setup so that one of the views loads up the Ember app from S3 - something like below in my application.html.erb:

  ...
  <body>
    <%= yield %>
    <%= ember_assets.script_tag_for('vendor') %>
    <%= ember_assets.script_tag_for('my-ember-frontend-app') %>

and this in my ApplicationController:

class ApplicationController < ActionController::Base
  helper_method def ember_assets
    @ember_assets ||= begin
      asset_loader = EmberAssets::FileLoader.new # responsible for loading JS from S3

      EmberAssets.new(request: request, asset_loader: asset_loader)
    end
  end
  ...

The Javascript loads fine because my EmberAssets Ruby class correctly points to and loads up the JS files from S3. However, I have the logo and a few other default assets stored in public/assets/images/... and I read from them in my Ember app like so:

<img src="/assets/images/logo.png" alt="logo">

The problem is that while the JS is loaded correctly, the image files are not loaded from S3.

the logo png request initiated by the built vendor.js fails with a 404

How do I make it so that my Ember app reads default assets from S3 as well? I checked S3 and the asset is in the correct folder as expected with fingerprint and all.

enter image description here

I'm using Rails 6 and Ember 3.25 and I have installed these ember-cli-deploy addons for building and deploying my Ember app.

    "ember-cli-deploy": "^1.0.2",
    "ember-cli-deploy-build": "^2.0.0",
    "ember-cli-deploy-json-config": "^1.0.1",
    "ember-cli-deploy-s3": "^3.0.0",

This is my build config. I tried to prepend my S3 bucket url but it didn't work:

module.exports = function (defaults) {
  let app = new EmberApp(defaults, {
    // Add options here

    fingerprint: {
      prepend: 'https://ember-s3-prod.s3.amazonaws.com/'
    }
  });
  ...

Thanks!




Cannot read property 'kind' of undefined in enger JS when adding objects to array

im new to ember js, and below is my code for create tags array from the selectedEntities array. its successfulyy console logs the values inside the selectedEntities array, but when adding created object (tag) values to tags array its always gives "Cannot read property 'tags' of undefined". How to solve this.

export default class Merchants extends Controller.extend(DebounceQueryParams) {
    tags= A([]); 
    selectedEntities = A([]); 
    
    
     @action
      openTestModal() {
        this.selectedEntities.forEach(function (e){
          console.log("name  ", e.contactInfo.contactName);
          console.log("e.id  ", e.id);
          if(e.workflowTask !==null){
            console.log("e.workflowTask.currentStatus  ", e.workflowTask.currentStatus);
            const tag = {
              id: e.id,
              name: e.contactInfo.contactName,
              status: e.workflowTask.currentStatus
            };
            this.tags.pushObject(tag);
          }
    
          const tag = {
            id: e.id,
            name: e.contactInfo.contactName,
            status: e.workflowTask.currentStatus
          };
          this.tags.pushObject(tag);
        });
        this.remodal.open('user-assign');
      }
}



dimanche 20 juin 2021

Can't build Ember.js app embedded in Rails app on Heroku

Trying to build Ember.js app embedded in Rails app on Heroku, but get this error:

Could not require 'ember-cli-build.js': Cannot find module 'ember-cli/lib/broccoli/ember-app'

Rail's package.json:

{
  "name": "foo",
  "license": "MIT",
  "engines": {
    "node": "9.5.0",
    "yarn": "1.22.4"
  },
  "scripts": {
    "build": "yarn global add ember-cli@2.9.0 --ignore-engines && yarn --cwd ember install --ignore-engines && yarn --cwd ember build"
  }
}

Ember's package.json:

{
  "name": "foo",
  "version": "0.0.0",
  "description": "foo",
  "private": true,
  "directories": {
    "doc": "doc",
    "test": "tests"
  },
  "scripts": {
    "build": "ember build",
    "start": "ember server",
    "test": "ember test"
  },
  ...
}

This Ember.js app as stand-alone, i.e. not being embedded in Rails app, is deployed on Heroku without errors.




zsh: command not found: ember

I installed ember through: npm install -g ember-cli, but after doing so when checking to see if the installation was successful , ember -v, it returns that the command is not found.

What could be the issue? Thank you.




mercredi 16 juin 2021

Why am i getting this ember-font-awesome error?

I upgraded the current Ember app from 3.20 to 3.26 and we are getting this error from ember-font-awesome.

Template Compiler Error (broccoli-persistent-filter:TemplateCompiler) in ember-font-awesome/components/fa-icon/template.hbs

loc$$1.sliceStartChars is not a function

Any quick ideas before I jump down a rabbit hole?




mardi 15 juin 2021

Fabric JS Tint Filter when applied resizes image Ember project

I have implemented Fabric in a Emberjs project, tinting a placed image causes the image to reduce in the lager markings

component handlebars

<div id="select-image-dimensions" class="placeholder canvas-size" >
</div>

component javascript

import Component from '@glimmer/component';
import ENV from '../config/environment';
import AWS from 'aws-sdk';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { fabric } from 'fabric';
import Picker from 'vanilla-picker';

export default class WallToDecorateComponent extends Component {
  @service('captured-image') capturedImage;
  @tracked canvasToDecorate = null;
  @tracked isDown = false;
  @tracked currentColor = null;

  @action
  renderWallCanvas() {
    var canvasAspect, imgAspectLandscape, imgAspectPortrait, left, top, scaleFactor, rect;
    let elemSize = document.querySelector('#select-image-dimensions');

    if(elemSize) {
      rect = elemSize.getBoundingClientRect();
      var canvas = document.createElement('canvas');
      canvas.id = 'fabric-canvas-to-decorate';
      canvas.width = rect.width;
      canvas.height = rect.height;
      elemSize.appendChild(canvas);
    }
    canvasAspect = rect.width / rect.height;
    imgAspectLandscape = this.capturedImage.wallImage.width / this.capturedImage.wallImage.height;
    imgAspectPortrait =  this.capturedImage.wallImage.height / this.capturedImage.wallImage.width;

    if (this.capturedImage.wallImage.width > this.capturedImage.wallImage.height) {

      if (canvasAspect >= imgAspectLandscape) {
          scaleFactor = rect.width / this.capturedImage.wallImage.width;
          left = 0;
          top = -((this.capturedImage.wallImage.height * scaleFactor) - rect.height) / 2;
      } else {
          scaleFactor = rect.height / this.capturedImage.wallImage.height;
          top = 0;
          left = -((this.capturedImage.wallImage.width * scaleFactor) - rect.width) / 2;
      }
    } else {

      if (canvasAspect >= imgAspectPortrait) {
          scaleFactor = rect.height / this.capturedImage.wallImage.height;
          left = -((this.capturedImage.wallImage.width * scaleFactor) - rect.width) / 2;
          top = -((this.capturedImage.wallImage.height * scaleFactor) - rect.height) / 2;
      } else {
          scaleFactor = rect.width / this.capturedImage.wallImage.width;
          top = 0;
          left = -((this.capturedImage.wallImage.width * scaleFactor) - rect.width) / 2;
      }
    }

    var canvas = new fabric.Canvas('fabric-canvas-to-decorate');
    canvas.setBackgroundImage(this.capturedImage.wallImage.src, canvas.renderAll.bind(canvas), {
        backgroundImageOpacity: 1,
        backgroundImageStretch: false,

        top: top,
        left: left,
        originX: 'left',
        originY: 'top',
        scaleX: scaleFactor,
        scaleY: scaleFactor
    });
    this.canvasToDecorate = canvas;
  }

  @action
  addImageTemplateToCanvas(event) {
    let targetElement = document.getElementById(event.target.id);
    var imgInstance = new fabric.Image(targetElement, {
      left: 100,
      top: 100,
      angle: 0,
      opacity: 1
    });
    this.canvasToDecorate.add(imgInstance);
  }

...    
  @action
  setColor() {
    if (!this.canvasToDecorate.getActiveObject()) {
      return;
    }

    var canvas2dBackend = new fabric.Canvas2dFilterBackend()
    fabric.filterBackend = canvas2dBackend;
    fabric.filterBackend = fabric.initFilterBackend();

    var colorButton = document.querySelector('#select-color');
    var obj = this.canvasToDecorate.getActiveObject();

    var filter = new fabric.Image.filters.BlendColor({
      color: colorButton.style.background,
      mode: 'tint',
      alpha: 0.5
    });

    obj.filters[16] = filter;
    obj.applyFilters();
    this.canvasToDecorate.renderAll();
  }

  @action
  selectColor() {
    var parent = document.querySelector('#select-color');
    var picker = new Picker(parent);

    picker.onDone = function(color) {
      parent.style.background = color.rgbaString;
    };
    this.currentColor = parent.style.background;
  }

When I select an image on the Fabric canvas to change the color, when the 'Tint' is applied the image resizes. Key section below.

  setColor() {
    if (!this.canvasToDecorate.getActiveObject()) {
      return;
    }

    var canvas2dBackend = new fabric.Canvas2dFilterBackend()
    fabric.filterBackend = canvas2dBackend;
    fabric.filterBackend = fabric.initFilterBackend();

    var colorButton = document.querySelector('#select-color');
    var obj = this.canvasToDecorate.getActiveObject();

    var filter = new fabric.Image.filters.BlendColor({
      color: colorButton.style.background,
      mode: 'tint',
      alpha: 0.5
    });

    obj.filters[16] = filter;
    obj.applyFilters();
    this.canvasToDecorate.renderAll();

The outline of the image doesn't change size but the actual image does,

enter image description here enter image description here




dimanche 13 juin 2021

Ember Octane - Mirage requestbody null

I am newbie on ember.js, trying to do some tests with mirage. Only certain fields of model come true, but the others come as null. As I am a newbie, I am not sure if the reason is about these lines

Account.js

const accountId = this.args.account.id;
var data = this.store.createRecord('subscription', 
{
  id:1,
  accountId: accountId,
  startDate: Date.now(),
  endDate: Date.now()
});
data.save();

Mirage - Config.js

this.post('/subscriptions', (schema, request) => {
    let requestBody = JSON.parse(request.requestBody);
    schema.subscriptions.push(requestBody);
  }, {timing: 2000});



lundi 7 juin 2021

Scrolling an ember light table

I have an ember light table and and a sort by filter. When the filter is triggered the table does not move back to the top position.

var scroll_pos=(0);          
  $('html, body, #lt-body').animate({scrollTop:(scroll_pos)}, 2000)

I tried giving the parent div an Id and pulling it in so the page would reset to the top and the table. I'm very new to ember and cannot figure out how to make the table scroll to the top when the filter is used.




How to connect mySQL and emberJS framework to send and retrieve data

I am attempting to connect the db with emberJS framework as user's answers and admin's question are to be stored in DB and retrieve and show the admin the answers (yes, like feedback form). How can I do it?




jeudi 3 juin 2021

Ember Data Table Check box column

Im new to emberJS, Below is my ember js code for data table , when user select on the table row its navigate to different page "goToMerchantsManage", that should not happen when user clicks on the check box. How can i skip the navigation only for the check box.

> 
>             <tr >

>               **<td><input type="checkbox"  > </td>**

>               
>                 <td> </td>
>               
>               
>                 <td>
>                   <div class="text-nowrap d-flex flex-wrap">
>                     
>                       
>                     
>                   </div>
>                 </td>
>               
>               
>                 <td>  </td>
>               



mercredi 2 juin 2021

I am getting the following error while trying to run ./watch

I changed to a new machine and from Visual Studio 2017 to Visual Studio 2019 I started getting the following errors when I was running watch command as below, which I used to do from the beginning

PS C:\GitSrsCodes\IMS\IMS.Ember> ./watch
ERROR in ./app/application/ApplicationController.js 5:0-42 Module not found: Error: Can’t resolve ‘constants’ in ‘C:\GitSrsCodes\IMS\IMS.Ember\app\application’

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to: - add a fallback ‘resolve.fallback: { “constants”: require.resolve(“constants-browserify”) }’ - install ‘constants-browserify’ If you don’t want to include a polyfill, you can use an empty module like this: resolve.fallback: { “constants”: false } @ ./.webpack/webpack-results.js 3:46-97 @ ./.webpack/webpack-app.js 1:0-30

ERROR in ./app/components/tuts-tests/tuts-tests.js 5:0-30 Module not found: Error: Can’t resolve ‘os’ in ‘C:\GitSrsCodes\IMS\IMS.Ember\app\components\tuts-tests’

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to: - add a fallback ‘resolve.fallback: { “os”: require.resolve(“os-browserify/browser”) }’ - install ‘os-browserify’ If you don’t want to include a polyfill, you can use an empty module like this: resolve.fallback: { “os”: false } @ ./.webpack/webpack-results.js 3:9632-9682 @ ./.webpack/webpack-app.js 1:0-30

ERROR in ./node_modules/ember-source/dist/ember.debug.js 6498:16-37 Module not found: Error: Can’t resolve ‘url’ in ‘C:\GitSrsCodes\IMS\IMS.Ember\node_modules\ember-source\dist’

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to: - add a fallback ‘resolve.fallback: { “url”: require.resolve(“url/”) }’ - install ‘url’ If you don’t want to include a polyfill, you can use an empty module like this: resolve.fallback: { “url”: false } @ ./.webpack/webpack-entry-dev.js 5:0-39

3 errors have detailed information that is not shown.    
    3 errors have detailed information that is not shown.
    Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.
    
And I am getting webpack 5.38.1 compiled with 3 errors and 3 warnings in 23239 ms

Any help please if possible?




Different access name for same model in Ember

i have a model in ember , called "post" ,so when i use store to get/delete data the request will be "/post" , is it possible to have another namespace like "/tenant" to access same model post ?

like post.delete() should send DELETE backend response as "/tenant/#id" instead of "/post/#id" . i am changing my backend api so want to change the frontend end point without changing the model name in frontend ,




How to create ember 2.8.0 project

I'm trying to create a ember 2.8.0 project.

Ember.js docs doesn't help me in creating a version specific project. : (

A few questions were asked in stackoverflow regarding this topic and those answers there were not working as none od them are accepted answers.

Can someone help me out ?