Skip to content

Commit

Permalink
feat: show user export button (projectcaluma#412)
Browse files Browse the repository at this point in the history
  • Loading branch information
czosel authored and derrabauke committed Apr 14, 2022
1 parent bb0f8f2 commit ecd31a0
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 10 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,22 @@ export default class App extends Application {
this.engines = {
"ember-emeis": {
dependencies: {
services: ["store", "intl", "notification", "router"],
services: ["store", "fetch", "intl", "notification", "router"],
},
},
};
}
});
```

Emeis requires the following services to be injects:

- `store` - almost all of the data fetching is done using ember data
- `fetch` - the user export requires a `fetch` services that handles authentication
- `intl` - ember-intl for i18n
- `notification` - handles success and error messages
- `router` - the ember router service

## Configuration

### Emeis options
Expand Down
23 changes: 18 additions & 5 deletions addon/components/section-title.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@
<h2 class="uk-margin-remove">
{{t (concat "emeis." @model ".title")}}
</h2>
{{#unless @noCreateLink}}
<LinkTo @route="{{@model}}.new" class="uk-button uk-button-primary" data-test-new>
{{t (concat "emeis." @model ".new")}}
</LinkTo>
{{/unless}}
<div>
{{#if @onExport}}
<UkButton
class="uk-margin-small-right"
@onClick={{@onExport}}
@disabled={{@onExport.isRunning}}
@loading={{@onExport.isRunning}}
>
<UkIcon class="icon-in-button" @icon="cloud-download" />
{{t "emeis.export"}}
</UkButton>
{{/if}}
{{#unless @noCreateLink}}
<LinkTo @route="{{@model}}.new" class="uk-button uk-button-primary" data-test-new>
{{t (concat "emeis." @model ".new")}}
</LinkTo>
{{/unless}}
</div>
</div>
<hr />
24 changes: 24 additions & 0 deletions addon/controllers/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Controller from "@ember/controller";
import { inject as service } from "@ember/service";
import { task } from "ember-concurrency";
import { saveAs } from "file-saver";

import { handleTaskErrors } from "ember-emeis/-private/decorators";

export default class UsersController extends Controller {
@service notification;
@service intl;
@service fetch;

@task
@handleTaskErrors
*export() {
const response = yield this.fetch.fetch(`/api/v1/users/export`);

const filename = response.headers
.get("content-disposition")
.match(/filename="(.*)"/)[1];

saveAs(yield response.blob(), filename);
}
}
9 changes: 8 additions & 1 deletion addon/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ export default class EmberEmeisEngine extends Engine {
Resolver = Resolver;

dependencies = {
services: ["store", "intl", "notification", "router", "emeis-options"],
services: [
"store",
"fetch",
"intl",
"notification",
"router",
"emeis-options",
],
};
}

Expand Down
3 changes: 3 additions & 0 deletions addon/services/fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Service from "@ember/service";

export default class FetchService extends Service {}
2 changes: 1 addition & 1 deletion addon/templates/users.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<SectionTitle @model="users" />
<SectionTitle @model="users" @onExport={{perform this.export}} />

{{outlet}}
1 change: 1 addition & 0 deletions app/controllers/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "ember-emeis/controllers/users";
1 change: 1 addition & 0 deletions app/services/fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "ember-emeis/services/fetch";
6 changes: 5 additions & 1 deletion app/styles/ember-emeis.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $ember-power-select-border-color: $global-border;
transition: width 0.3s ease-out;
}

// fixes the negative margin overlapp of uk-grid
// fixes the negative margin overlap of uk-grid
.uk-grid-divider-fix {
margin-left: 0;

Expand All @@ -33,6 +33,10 @@ div.uk-grid-divider-fix.uk-grid-stack > .uk-grid-margin::before {
outline: inherit;
}

.icon-in-button {
margin-right: 0.3rem;
}

.pointer {
cursor: pointer;
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"ember-simple-set-helper": "^0.1.2",
"ember-test-selectors": "^6.0.0",
"ember-truth-helpers": "^3.0.0",
"ember-uikit": "^5.0.0"
"ember-uikit": "^5.0.0",
"file-saver": "^2.0.5"
},
"devDependencies": {
"@adfinis-sygroup/eslint-config": "1.5.0",
Expand Down
1 change: 1 addition & 0 deletions tests/dummy/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default class App extends Application {
dependencies: {
services: [
"store",
"fetch",
"intl",
"notification",
"router",
Expand Down
54 changes: 54 additions & 0 deletions tests/dummy/app/services/fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import Service from "@ember/service";
import { isEmpty } from "@ember/utils";

const cleanObject = (obj) => {
return Object.entries(obj).reduce((clean, [key, value]) => {
return {
...clean,
...(isEmpty(value) ? {} : { [key]: value }),
};
}, {});
};

export default class FetchService extends Service {
async fetch(resource, init = {}) {
init.headers = cleanObject({
...this.headers,
...(init.headers || {}),
});

const response = await fetch(resource, init);
if (!response.ok) {
if (response.status === 401) {
// handle unauthorized case
return;
}

const contentType = response.headers.get("content-type");
let body = "";

if (/^application\/(vnd\.api+)?json$/.test(contentType)) {
body = await response.json();
} else if (contentType === "text/plain") {
body = await response.text();
}

// throw an error containing a human readable message
throw {
response,
body,
error: new Error(
`Fetch request to URL ${response.url} returned ${response.status} ${response.statusText}:\n\n${body}`
),
};
}

return response;
}

get headers() {
return {
// authorization: "Bearer 123123123",
};
}
}
12 changes: 12 additions & 0 deletions tests/unit/controllers/users-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { setupTest } from "ember-qunit";
import { module, test } from "qunit";

module("Unit | Controller | users", function (hooks) {
setupTest(hooks);

// TODO: Replace this with your real tests.
test("it exists", function (assert) {
const controller = this.owner.lookup("controller:users");
assert.ok(controller);
});
});
1 change: 1 addition & 0 deletions translations/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ emeis:
loading: "Laden..."
general-error: "Ein Problem ist aufgetretten. Bitte versuchen Sie es erneut."
actions: "Aktionen"
export: "Export"

scopes:
title: "Organisationen"
Expand Down
1 change: 1 addition & 0 deletions translations/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ emeis:
loading: "Loading..."
general-error: "A problem occured. Please try again."
actions: "Actions"
export: "Export"

scopes:
title: "Scopes"
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8785,6 +8785,11 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"

file-saver@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==

[email protected]:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
Expand Down

0 comments on commit ecd31a0

Please sign in to comment.