@fleetbase/solid-engine 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +651 -21
- package/README.md +89 -18
- package/addon/components/explorer-header.hbs +18 -0
- package/addon/components/explorer-header.js +25 -0
- package/addon/components/modals/backup-pod.hbs +3 -0
- package/addon/components/modals/create-pod.hbs +5 -0
- package/addon/components/modals/resync-pod.hbs +3 -0
- package/addon/components/table/cell/pod-content-actions.hbs +32 -0
- package/addon/components/table/cell/pod-content-actions.js +73 -0
- package/addon/components/table/cell/pod-content-name.hbs +8 -0
- package/addon/components/table/cell/pod-content-name.js +16 -0
- package/addon/controllers/account.js +130 -0
- package/addon/controllers/application.js +16 -13
- package/addon/controllers/home.js +23 -0
- package/addon/controllers/pods/explorer/content.js +12 -0
- package/addon/controllers/pods/explorer.js +149 -0
- package/addon/controllers/pods/index/pod.js +12 -0
- package/addon/controllers/pods/index.js +137 -0
- package/addon/routes/account.js +3 -0
- package/addon/routes/home.js +3 -0
- package/addon/routes/pods/explorer/content.js +10 -0
- package/addon/routes/pods/explorer.js +44 -0
- package/addon/routes/pods/index/pod.js +3 -0
- package/addon/routes/pods/index.js +21 -0
- package/addon/routes.js +12 -1
- package/addon/services/explorer-state.js +101 -0
- package/addon/styles/solid-engine.css +46 -0
- package/addon/templates/account.hbs +42 -0
- package/addon/templates/application.hbs +17 -12
- package/addon/templates/home.hbs +11 -0
- package/addon/templates/pods/explorer/content.hbs +19 -0
- package/addon/templates/pods/explorer.hbs +20 -0
- package/addon/templates/pods/index/pod.hbs +11 -0
- package/addon/templates/pods/index.hbs +19 -0
- package/app/components/explorer-header.js +1 -0
- package/app/components/modals/backup-pod.js +1 -0
- package/app/components/modals/create-pod.js +1 -0
- package/app/components/modals/resync-pod.js +1 -0
- package/app/components/table/cell/pod-content-actions.js +1 -0
- package/app/components/table/cell/pod-content-name.js +1 -0
- package/app/controllers/account.js +1 -0
- package/app/controllers/home.js +1 -0
- package/app/controllers/pods/explorer/content.js +1 -0
- package/app/controllers/pods/explorer.js +1 -0
- package/app/controllers/pods/index/pod.js +1 -0
- package/app/controllers/pods/index.js +1 -0
- package/app/routes/account.js +1 -0
- package/app/routes/home.js +1 -0
- package/app/routes/pods/explorer/content.js +1 -0
- package/app/routes/pods/explorer.js +1 -0
- package/app/routes/pods/index/pod.js +1 -0
- package/app/routes/pods/index.js +1 -0
- package/app/services/explorer-state.js +1 -0
- package/app/templates/account.js +1 -0
- package/app/templates/home.js +1 -0
- package/app/templates/pods/explorer/content.js +1 -0
- package/app/templates/pods/explorer.js +1 -0
- package/app/templates/pods/index/pod.js +1 -0
- package/app/templates/pods/index.js +1 -0
- package/composer.json +10 -4
- package/extension.json +2 -2
- package/package.json +5 -5
- package/server/data/pods.json +328 -0
- package/server/src/Client/OpenIDConnectClient.php +2 -2
- package/server/src/Client/SolidClient.php +1 -1
- package/server/src/Http/Controllers/SolidController.php +57 -4
- package/server/src/LegacyClient/OIDCClient.php +1 -1
- package/server/src/LegacyClient/SolidClient.php +2 -1
- package/server/src/Support/Utils.php +38 -0
- package/server/src/routes.php +1 -0
package/README.md
CHANGED
|
@@ -61,6 +61,7 @@ Solid, an innovative technology developed by Sir Tim Berners-Lee, offers a groun
|
|
|
61
61
|
- Input their server
|
|
62
62
|
- Input their solid ID on the server
|
|
63
63
|
- Once installed, users signing up or added to the company within this instance can utilize Solid for data management.
|
|
64
|
+
- More info: The interface which allows the instance administrator to link the Fleetbase Solid extension to the Solid server of their preference. Due to the nature of how Solid is built on an identity basis, and Fleetbase is built as a multi-tenant platform. Each organization on Fleetbase when accessing the instance will be prompted to link their Solid OIDC account [https://github.com/fleetbase/solid/blob/main/addon/controllers/application.js#L16] to their Fleetbase organization per the instance. Once linked all data synced between Solid and Fleetbase will be via the SolidIdentity [https://github.com/fleetbase/solid/blob/main/server/src/Models/SolidIdentity.php]
|
|
64
65
|
|
|
65
66
|
### User Authentication and Account Creation:
|
|
66
67
|
|
|
@@ -69,27 +70,97 @@ Solid, an innovative technology developed by Sir Tim Berners-Lee, offers a groun
|
|
|
69
70
|
- Authorize fleetbase.io to access your Pod.
|
|
70
71
|
- Solid allows precise control over data access permissions. Note: The current UI version (node-solid-server V5.1) supports toggling global access permissions only. If you prefer granular control, uncheck all boxes and authorize. Then, manage permissions explicitly.
|
|
71
72
|
|
|
73
|
+
### Fleetbase UI Updates
|
|
74
|
+
|
|
75
|
+
Developer/User Guide:
|
|
76
|
+
|
|
77
|
+
Fleetbase Solid ExtensionThis guide provides detailed instructions for integrating the Solid extension with your Fleetbase account. Solid is an innovative technology that lets users store their own data in personal online data stores, called "Pods," that they control. By using the Solid extension on Fleetbase, users can manage their data directly through the Fleetbase interface.
|
|
78
|
+
|
|
79
|
+
1. Create a New Fleetbase Account
|
|
80
|
+
- If you don't already have a Fleetbase account, you'll need to create one:
|
|
81
|
+
|
|
82
|
+
- Go to the Fleetbase website
|
|
83
|
+
- Click on "Sign Up" and follow the registration process.
|
|
84
|
+
- Verify your account as required.
|
|
85
|
+
|
|
86
|
+

|
|
87
|
+
|
|
88
|
+
2. Install the Solid Extension
|
|
89
|
+
- Once your Fleetbase account is active, follow these steps to install the Solid extension:
|
|
90
|
+
|
|
91
|
+
- Log in to your Fleetbase dashboard.Navigate to the Extensions section.
|
|
92
|
+
- Find the Solid extension and click "Install."Fleetbase Extensions Registry will be launching Q3 2024
|
|
93
|
+
|
|
94
|
+
3. Admin Configuration
|
|
95
|
+
- As an admin, you need to set up the Solid server for your organization:
|
|
96
|
+
|
|
97
|
+
- After installation, navigate to Admin so you can configure the Solid extension settings.
|
|
98
|
+
- Input the Solid server ID where your organization's data will be stored. This might be a private server or a service like solidcommunity.net
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
4. Get Started with Solid
|
|
104
|
+
- Users must individually sign up for a Solid account:
|
|
105
|
+
|
|
106
|
+
- Click ‘Sign up for an account’ or Visit https://solidcommunity.net/register or your organization's own Solid server.
|
|
107
|
+
- Complete the registration process to create a new Solid account.
|
|
108
|
+
|
|
109
|
+

|
|
110
|
+
|
|
111
|
+
5. Retrieve Your Web ID
|
|
112
|
+
- Your Web ID is your unique identifier in the Solid ecosystem:
|
|
113
|
+
|
|
114
|
+
- After registering, your Web ID will typically be displayed on your Solid dashboard.Note this Web ID as it will be used to link your Solid account with Fleetbase.
|
|
115
|
+
|
|
116
|
+

|
|
117
|
+
|
|
118
|
+
6. Navigate to ‘Account’ in Fleetbase
|
|
119
|
+
- Once your Web ID is set up:Go back to Fleetbase and navigate to the ‘Account’ section. Your User details should be pulled in automatically if properly configured.
|
|
120
|
+
|
|
121
|
+

|
|
122
|
+
|
|
123
|
+
7. Navigate to PodsTo manage your Pods:
|
|
124
|
+
- In Fleetbase, find and navigate to the ‘Pods’ section after linking your Solid account.
|
|
125
|
+
|
|
126
|
+

|
|
127
|
+
|
|
128
|
+
8. Create a New POD
|
|
129
|
+
- Here’s how to create a new POD:
|
|
130
|
+
|
|
131
|
+
- Click “Create New POD.”Enter a name for your POD and submit.
|
|
132
|
+
|
|
133
|
+

|
|
134
|
+
|
|
135
|
+
9. Manage Files/Folders in PODs
|
|
136
|
+
- To access and manage data within a POD:
|
|
137
|
+
|
|
138
|
+
- Click into the POD you wish to view.
|
|
139
|
+
- You’ll see files and folders stored in this POD
|
|
140
|
+
|
|
141
|
+

|
|
142
|
+
|
|
143
|
+
10. Operations on PODsSelect
|
|
144
|
+
|
|
145
|
+
- Box Delete: To delete files or folders, select them and use the delete option.
|
|
146
|
+
- Re-sync / Back Up the PODs: To ensure your data is up-to-date, use the re-sync option to resynchronize the data in the POD.
|
|
147
|
+
|
|
148
|
+

|
|
149
|
+
|
|
150
|
+
11. View Data in Pods
|
|
151
|
+
- To view specific data within a POD:
|
|
152
|
+
|
|
153
|
+
- Simply click on the file or folder you are interested in within the POD interface in Fleetbase.
|
|
154
|
+
|
|
155
|
+

|
|
156
|
+
|
|
157
|
+
Next: We will continue work on completing the Sold <> Fleetbase integration with the following Further User Interface (UI) Enhancement for renaming Pods. Extensive User testing / bug fixes and production release.
|
|
158
|
+
|
|
72
159
|
### Features:
|
|
73
160
|
|
|
161
|
+
Fleetbase has implemented a Solid Client which implements the Standard Solid authentication methods to communicate with the server. The Fleetbase SolidClient is able to communicate securely with the Solid protocol using the Standard DPoP encryption method for authentication provided by the Solid specification (https://solidproject.org/TR/oidc#tokens-id)
|
|
162
|
+
|
|
74
163
|
- Ability to link Fleetbase account with Solid Web ID later via user settings.
|
|
75
|
-
- View and manage data stored on Solid Pod:
|
|
76
|
-
- Orders
|
|
77
|
-
- Payload
|
|
78
|
-
- Entity
|
|
79
|
-
- Service Quote
|
|
80
|
-
- Purchase Rate
|
|
81
|
-
- Retrieve list of Solid Pods approved to receive data.
|
|
82
|
-
- Ability to add approved pods to send order data too (Verification Process)
|
|
83
|
-
- View order details
|
|
84
|
-
- Send order details
|
|
85
|
-
- Select Pod to send order details too
|
|
86
|
-
- Send order details to Solid partners:
|
|
87
|
-
- View Order
|
|
88
|
-
- Send Order
|
|
89
|
-
- Select from Dropdown of Solid Partners
|
|
90
|
-
- Confirmation popup for sending data
|
|
91
|
-
- Review and confirm data to be sent
|
|
92
|
-
- Access a separate table to view all data shared with you or shared with other Solid users.
|
|
93
164
|
|
|
94
165
|
# Funding
|
|
95
166
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<div id="next-view-section-subheader" class="next-view-section-subheader {{if @hideActions 'actions-hidden'}}" ...attributes>
|
|
2
|
+
<div id="next-view-section-subheader-left" class="next-view-section-subheader-left {{@leftSubheaderClass}}">
|
|
3
|
+
<div class="flex flex-row items-center">
|
|
4
|
+
<FaIcon @icon="folder-tree" @size="sm" class="{{@iconClass}} text-gray-200 dark:text-gray-600 mr-2" />
|
|
5
|
+
<div class="pod-explorer-breadcrumb-container">
|
|
6
|
+
{{#each this.state as |content|}}
|
|
7
|
+
<a href="#" class="pod-explorer-breadcrumb {{if (eq @current content.id) "active-breadcrumb"}} {{@breadcrumbClass}}" {{on "click" (fn this.onStateClicked content)}}>{{content.name}}</a>
|
|
8
|
+
{{/each}}
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
<div id="next-view-section-subheader-actions" class="next-view-section-subheader-actions {{@actionsWrapperClass}}">
|
|
13
|
+
{{#if @onSearch}}
|
|
14
|
+
<Input @type="text" @value={{@searchQuery}} aria-label={{t "common.search-input"}} placeholder={{or @searchPlaceholder (concat (t "common.search") " " (pluralize @title))}} class="w-64 mr-2 form-input form-input-sm {{@searchInputClass}}" {{on "keyup" @onSearch}} />
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{yield}}
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { inject as service } from '@ember/service';
|
|
4
|
+
import { action } from '@ember/object';
|
|
5
|
+
|
|
6
|
+
export default class ExplorerHeaderComponent extends Component {
|
|
7
|
+
@service explorerState;
|
|
8
|
+
@tracked state = [];
|
|
9
|
+
|
|
10
|
+
constructor(owner, { pod }) {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.state = this.explorerState.get(pod);
|
|
13
|
+
this.explorerState.on('change', (id, state) => {
|
|
14
|
+
if (id === pod) {
|
|
15
|
+
this.state = state;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@action onStateClicked(content) {
|
|
21
|
+
if (typeof this.args.onStateClicked === 'function') {
|
|
22
|
+
this.args.onStateClicked(content);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
|
|
2
|
+
<div class="modal-body-container">
|
|
3
|
+
<InputGroup @name="Pod Name" @value={{@options.pod.name}} @helpText="Input a name for your new Pod" />
|
|
4
|
+
</div>
|
|
5
|
+
</Modal::Default>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<div class="cell-dropdown-button overflow-visible {{@column.wrapperClass}}" {{did-insert this.setupComponent}} ...attributes>
|
|
2
|
+
<DropdownButton @icon={{@column.ddButtonIcon}} @iconPrefix={{@column.ddButtonIconPrefix}} @text={{this.buttonText}} @size="xs" @horizontalPosition="left" @calculatePosition={{this.calculatePosition}} @renderInPlace={{true}} as |dd|>
|
|
3
|
+
<div class="next-dd-menu mt-0i" role="menu" aria-orientation="vertical" aria-labelledby="user-menu">
|
|
4
|
+
{{#if @column.ddMenuLabel}}
|
|
5
|
+
<div class="px-1">
|
|
6
|
+
<div class="text-sm flex flex-row items-center px-3 py-1 rounded-md my-1 text-gray-800 dark:text-gray-300">
|
|
7
|
+
{{@column.ddMenuLabel}}
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="next-dd-menu-seperator"></div>
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#each this.actions as |action|}}
|
|
13
|
+
{{#if action.separator}}
|
|
14
|
+
<div class="next-dd-menu-seperator"></div>
|
|
15
|
+
{{else}}
|
|
16
|
+
{{#if (is-dd-item-visible @row action.isVisible)}}
|
|
17
|
+
<div role="group" class="px-1">
|
|
18
|
+
<a href="javascript:;" role="menuitem" class="next-dd-item {{action.class}}" {{on "click" (fn this.onDropdownItemClick action @row dd)}}>
|
|
19
|
+
{{#if action.icon}}
|
|
20
|
+
<span class="mr-1">
|
|
21
|
+
<FaIcon class={{action.iconClass}} @icon={{action.icon}} @prefix={{action.iconPrefix}} />
|
|
22
|
+
</span>
|
|
23
|
+
{{/if}}
|
|
24
|
+
{{action.label}}
|
|
25
|
+
</a>
|
|
26
|
+
</div>
|
|
27
|
+
{{/if}}
|
|
28
|
+
{{/if}}
|
|
29
|
+
{{/each}}
|
|
30
|
+
</div>
|
|
31
|
+
</DropdownButton>
|
|
32
|
+
</div>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action, computed } from '@ember/object';
|
|
4
|
+
import { isArray } from '@ember/array';
|
|
5
|
+
|
|
6
|
+
export default class TableCellPodContentActionsComponent extends Component {
|
|
7
|
+
constructor(owner, { column, row }) {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
if (isArray(column.actions)) {
|
|
10
|
+
this.actions = column.actions;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (typeof column.actions === 'function') {
|
|
14
|
+
this.actions = column.actions(row);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@tracked actions = [];
|
|
19
|
+
@tracked defaultButtonText = 'Actions';
|
|
20
|
+
|
|
21
|
+
@computed('args.column.ddButtonText', 'defaultButtonText') get buttonText() {
|
|
22
|
+
const { ddButtonText } = this.args.column;
|
|
23
|
+
|
|
24
|
+
if (ddButtonText === undefined) {
|
|
25
|
+
return this.defaultButtonText;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (ddButtonText === false) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return ddButtonText;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@action setupComponent(dropdownWrapperNode) {
|
|
36
|
+
const tableCellNode = this.getOwnerTableCell(dropdownWrapperNode);
|
|
37
|
+
tableCellNode.style.overflow = 'visible';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@action getOwnerTableCell(dropdownWrapperNode) {
|
|
41
|
+
while (dropdownWrapperNode) {
|
|
42
|
+
dropdownWrapperNode = dropdownWrapperNode.parentNode;
|
|
43
|
+
|
|
44
|
+
if (dropdownWrapperNode.tagName.toLowerCase() === 'td') {
|
|
45
|
+
return dropdownWrapperNode;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@action onDropdownItemClick(columnAction, row, dd) {
|
|
53
|
+
if (typeof dd?.actions?.close === 'function') {
|
|
54
|
+
dd.actions.close();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (typeof columnAction?.fn === 'function') {
|
|
58
|
+
columnAction.fn(row);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@action calculatePosition(trigger) {
|
|
63
|
+
let { width } = trigger.getBoundingClientRect();
|
|
64
|
+
|
|
65
|
+
let style = {
|
|
66
|
+
marginTop: '0px',
|
|
67
|
+
right: width + 3,
|
|
68
|
+
top: 0,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return { style };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<a href="#" {{on "click" this.onClick}} class={{@column.anchorClass}} disabled={{not @value}} ...attributes>
|
|
2
|
+
{{#if (has-block)}}
|
|
3
|
+
{{yield}}
|
|
4
|
+
{{else}}
|
|
5
|
+
<FaIcon @icon={{@row.type}} @size="xs" class="mr-1" />
|
|
6
|
+
<span class={{@column.anchorSpanClass}}>{{or @value @column.anchorText "-"}}</span>
|
|
7
|
+
{{/if}}
|
|
8
|
+
</a>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { action } from '@ember/object';
|
|
3
|
+
|
|
4
|
+
export default class TableCellPodContentNameComponent extends Component {
|
|
5
|
+
@action onClick() {
|
|
6
|
+
const { column, row } = this.args;
|
|
7
|
+
|
|
8
|
+
if (typeof column?.action === 'function') {
|
|
9
|
+
column.action(row);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (typeof column?.onClick === 'function') {
|
|
13
|
+
column.onClick(row, ...arguments);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
import { action } from '@ember/object';
|
|
4
|
+
import { alias } from '@ember/object/computed';
|
|
5
|
+
import { task } from 'ember-concurrency';
|
|
6
|
+
|
|
7
|
+
export default class AccountController extends Controller {
|
|
8
|
+
/**
|
|
9
|
+
* Inject the `currentUser` service.
|
|
10
|
+
*
|
|
11
|
+
* @memberof ConsoleAccountIndexController
|
|
12
|
+
*/
|
|
13
|
+
@service currentUser;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Inject the `fetch` service.
|
|
17
|
+
*
|
|
18
|
+
* @memberof ConsoleAccountIndexController
|
|
19
|
+
*/
|
|
20
|
+
@service fetch;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Inject the `notifications` service.
|
|
24
|
+
*
|
|
25
|
+
* @memberof ConsoleAccountIndexController
|
|
26
|
+
*/
|
|
27
|
+
@service notifications;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Inject the `modalsManager` service.
|
|
31
|
+
*
|
|
32
|
+
* @memberof ConsoleAccountIndexController
|
|
33
|
+
*/
|
|
34
|
+
@service modalsManager;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Alias to the currentUser service user record.
|
|
38
|
+
*
|
|
39
|
+
* @memberof ConsoleAccountIndexController
|
|
40
|
+
*/
|
|
41
|
+
@alias('currentUser.user') user;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Handle upload of new photo
|
|
45
|
+
*
|
|
46
|
+
* @param {UploadFile} file
|
|
47
|
+
* @memberof ConsoleAccountIndexController
|
|
48
|
+
*/
|
|
49
|
+
@action uploadNewPhoto(file) {
|
|
50
|
+
return this.fetch.uploadFile.perform(
|
|
51
|
+
file,
|
|
52
|
+
{
|
|
53
|
+
path: `uploads/${this.user.company_uuid}/users/${this.user.slug}`,
|
|
54
|
+
subject_uuid: this.user.id,
|
|
55
|
+
subject_type: 'user',
|
|
56
|
+
type: 'user_avatar',
|
|
57
|
+
},
|
|
58
|
+
(uploadedFile) => {
|
|
59
|
+
this.user.setProperties({
|
|
60
|
+
avatar_uuid: uploadedFile.id,
|
|
61
|
+
avatar_url: uploadedFile.url,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return this.user.save();
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Starts the task to change password
|
|
71
|
+
*
|
|
72
|
+
* @param {Event} event
|
|
73
|
+
* @memberof ConsoleAccountIndexController
|
|
74
|
+
*/
|
|
75
|
+
@task *saveProfile(event) {
|
|
76
|
+
// If from event fired
|
|
77
|
+
if (event instanceof Event) {
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let canUpdateProfile = true;
|
|
82
|
+
// If email has been changed prompt for password validation
|
|
83
|
+
if (this.changedUserAttribute('email')) {
|
|
84
|
+
canUpdateProfile = yield this.validatePassword.perform();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (canUpdateProfile === true) {
|
|
88
|
+
try {
|
|
89
|
+
const user = yield this.user.save();
|
|
90
|
+
this.notifications.success('Profile changes saved.');
|
|
91
|
+
this.currentUser.set('user', user);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
this.notifications.serverError(error);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
this.user.rollbackAttributes();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Task to validate current password
|
|
102
|
+
*
|
|
103
|
+
* @return {boolean}
|
|
104
|
+
* @memberof ConsoleAccountIndexController
|
|
105
|
+
*/
|
|
106
|
+
@task *validatePassword() {
|
|
107
|
+
let isPasswordValid = false;
|
|
108
|
+
|
|
109
|
+
yield this.modalsManager.show('modals/validate-password', {
|
|
110
|
+
body: 'You must validate your password to update the account email address.',
|
|
111
|
+
onValidated: (isValid) => {
|
|
112
|
+
isPasswordValid = isValid;
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return isPasswordValid;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Checks if any user attribute has been changed
|
|
121
|
+
*
|
|
122
|
+
* @param {string} attributeKey
|
|
123
|
+
* @return {boolean}
|
|
124
|
+
* @memberof ConsoleAccountIndexController
|
|
125
|
+
*/
|
|
126
|
+
changedUserAttribute(attributeKey) {
|
|
127
|
+
const changedAttributes = this.user.changedAttributes();
|
|
128
|
+
return changedAttributes[attributeKey] !== undefined;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
import Controller from '@ember/controller';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
|
-
import {
|
|
3
|
+
import { tracked } from '@glimmer/tracking';
|
|
4
|
+
import { task, timeout } from 'ember-concurrency';
|
|
4
5
|
|
|
5
6
|
export default class ApplicationController extends Controller {
|
|
6
|
-
@service universe;
|
|
7
7
|
@service fetch;
|
|
8
|
+
@service appCache;
|
|
9
|
+
@tracked pods = [];
|
|
8
10
|
|
|
9
11
|
constructor() {
|
|
10
12
|
super(...arguments);
|
|
11
|
-
this.
|
|
12
|
-
sidebarContext.hideNow();
|
|
13
|
-
});
|
|
13
|
+
this.getPods.perform();
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
@task *
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
@task *getPods() {
|
|
17
|
+
yield timeout(600);
|
|
18
|
+
|
|
19
|
+
if (this.appCache.has('solid:pods')) {
|
|
20
|
+
this.pods = this.appCache.get('solid:pods', []);
|
|
21
|
+
return;
|
|
20
22
|
}
|
|
21
|
-
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
try {
|
|
25
|
+
this.pods = yield this.fetch.get('pods', {}, { namespace: 'solid/int/v1' });
|
|
26
|
+
} catch (error) {
|
|
27
|
+
// silence
|
|
28
|
+
}
|
|
26
29
|
}
|
|
27
30
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
import { task } from 'ember-concurrency';
|
|
4
|
+
|
|
5
|
+
export default class HomeController extends Controller {
|
|
6
|
+
@service fetch;
|
|
7
|
+
@service notifications;
|
|
8
|
+
|
|
9
|
+
@task *authenticate() {
|
|
10
|
+
try {
|
|
11
|
+
const { authenticationUrl, identifier } = yield this.fetch.get('request-authentication', {}, { namespace: 'solid/int/v1' });
|
|
12
|
+
if (authenticationUrl) {
|
|
13
|
+
window.location.href = `${authenticationUrl}/${identifier}`;
|
|
14
|
+
}
|
|
15
|
+
} catch (error) {
|
|
16
|
+
this.notifications.serverError(error);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@task *getAccountIndex() {
|
|
21
|
+
yield this.fetch.get('account', {}, { namespace: 'solid/int/v1' });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { action } from '@ember/object';
|
|
3
|
+
|
|
4
|
+
export default class PodsExplorerContentController extends Controller {
|
|
5
|
+
@action setOverlayContext(overlayContextApi) {
|
|
6
|
+
this.overlayContextApi = overlayContextApi;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@action onPressClose() {
|
|
10
|
+
window.history.back();
|
|
11
|
+
}
|
|
12
|
+
}
|