WIP MSW setup
This commit is contained in:
@@ -1,14 +1,8 @@
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, query, state } from 'lit/decorators.js';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbContextConsumerMixin } from '../../../../../core/context';
|
||||
import { Subscription } from 'rxjs';
|
||||
import './list-view-layouts/table/editor-view-users-table.element';
|
||||
import './editor-view-users-grid.element';
|
||||
import './editor-view-users-selection.element';
|
||||
import { IRoute } from 'router-slot';
|
||||
import UmbEditorViewUsersElement, { UserItem } from './editor-view-users.element';
|
||||
import { UUIPopoverElement } from '@umbraco-ui/uui';
|
||||
import UmbEditorViewUsersElement from './editor-view-users.element';
|
||||
|
||||
export type UsersViewType = 'list' | 'grid';
|
||||
@customElement('umb-editor-view-users-invite')
|
||||
|
||||
@@ -4,7 +4,7 @@ import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbContextConsumerMixin } from '../../../../../core/context';
|
||||
import { Subscription } from 'rxjs';
|
||||
import './list-view-layouts/table/editor-view-users-table.element';
|
||||
import './editor-view-users-grid.element';
|
||||
import './list-view-layouts/grid/editor-view-users-grid.element';
|
||||
import './editor-view-users-selection.element';
|
||||
import './editor-view-users-invite.element';
|
||||
import { IRoute } from 'router-slot';
|
||||
@@ -132,7 +132,7 @@ export class UmbEditorViewUsersOverviewElement extends UmbContextConsumerMixin(L
|
||||
private _routes: IRoute[] = [
|
||||
{
|
||||
path: 'grid',
|
||||
component: () => import('./editor-view-users-grid.element'),
|
||||
component: () => import('./list-view-layouts/grid/editor-view-users-grid.element'),
|
||||
},
|
||||
{
|
||||
path: 'list',
|
||||
|
||||
@@ -4,7 +4,6 @@ import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbContextConsumerMixin } from '../../../../../core/context';
|
||||
import UmbEditorViewUsersElement, { UserItem } from './editor-view-users.element';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { tempData } from './tempData';
|
||||
import '../../../../property-editors/content-picker/property-editor-content-picker.element';
|
||||
|
||||
@customElement('umb-editor-view-users-user-details')
|
||||
@@ -86,20 +85,7 @@ export class UmbEditorViewUsersUserDetailsElement extends UmbContextConsumerMixi
|
||||
protected _usersContext?: UmbEditorViewUsersElement;
|
||||
protected _usersSubscription?: Subscription;
|
||||
|
||||
private _languages = tempData //TODO Get languages from API instead of fakeData
|
||||
.reduce((acc, curr) => {
|
||||
if (!acc.includes(curr.language)) {
|
||||
acc.push(curr.language);
|
||||
}
|
||||
return acc;
|
||||
}, [] as Array<string>)
|
||||
.map((language) => {
|
||||
return {
|
||||
name: language,
|
||||
value: language,
|
||||
selected: false,
|
||||
};
|
||||
});
|
||||
private _languages = []; //TODO Add languages
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
|
||||
@@ -12,23 +12,7 @@ import './editor-view-users-selection.element';
|
||||
import './editor-view-users-user-details.element';
|
||||
import './editor-view-users-invite.element';
|
||||
|
||||
import { tempData } from './tempData';
|
||||
|
||||
export interface UserItem {
|
||||
id: number;
|
||||
key: string;
|
||||
name: string;
|
||||
email: string;
|
||||
status: string;
|
||||
language: string;
|
||||
lastLoginDate?: string;
|
||||
lastLockoutDate?: string;
|
||||
lastPasswordChangeDate?: string;
|
||||
updateDate: string;
|
||||
createDate: string;
|
||||
failedLoginAttempts: number;
|
||||
userGroup?: string; //TODO Implement this
|
||||
}
|
||||
import type { UserDetails, UserEntity } from '../../../../../core/models';
|
||||
|
||||
@customElement('umb-editor-view-users')
|
||||
export class UmbEditorViewUsersElement extends UmbContextProviderMixin(LitElement) {
|
||||
@@ -54,9 +38,6 @@ export class UmbEditorViewUsersElement extends UmbContextProviderMixin(LitElemen
|
||||
},
|
||||
];
|
||||
|
||||
private _users: BehaviorSubject<Array<UserItem>> = new BehaviorSubject(tempData);
|
||||
public readonly users: Observable<Array<UserItem>> = this._users.asObservable();
|
||||
|
||||
private _selection: BehaviorSubject<Array<string>> = new BehaviorSubject(<Array<string>>[]);
|
||||
public readonly selection: Observable<Array<string>> = this._selection.asObservable();
|
||||
|
||||
@@ -84,45 +65,45 @@ export class UmbEditorViewUsersElement extends UmbContextProviderMixin(LitElemen
|
||||
this.requestUpdate('selection');
|
||||
}
|
||||
|
||||
public updateUser(user: UserItem) {
|
||||
const users = this._users.getValue();
|
||||
const index = users.findIndex((u) => u.key === user.key);
|
||||
if (index === -1) return;
|
||||
users[index] = { ...users[index], ...user };
|
||||
console.log('updateUser', user, users[index]);
|
||||
this._users.next(users);
|
||||
this.requestUpdate('users');
|
||||
}
|
||||
// public updateUser(user: UserEntity) {
|
||||
// const users = this._users.getValue();
|
||||
// const index = users.findIndex((u) => u.key === user.key);
|
||||
// if (index === -1) return;
|
||||
// users[index] = { ...users[index], ...user };
|
||||
// console.log('updateUser', user, users[index]);
|
||||
// this._users.next(users);
|
||||
// this.requestUpdate('users');
|
||||
// }
|
||||
|
||||
public inviteUser(name: string, email: string, userGroup: string, message: string): UserItem {
|
||||
const users = this._users.getValue();
|
||||
const user = {
|
||||
id: this._users.getValue().length + 1,
|
||||
key: uuidv4(),
|
||||
name: name,
|
||||
email: email,
|
||||
status: 'invited',
|
||||
language: 'en',
|
||||
updateDate: new Date().toISOString(),
|
||||
createDate: new Date().toISOString(),
|
||||
failedLoginAttempts: 0,
|
||||
userGroup: userGroup,
|
||||
};
|
||||
this._users.next([...users, user]);
|
||||
this.requestUpdate('users');
|
||||
// public inviteUser(name: string, email: string, userGroup: string, message: string): UserEntity {
|
||||
// const users = this._users.getValue();
|
||||
// const user = {
|
||||
// id: this._users.getValue().length + 1,
|
||||
// key: uuidv4(),
|
||||
// name: name,
|
||||
// email: email,
|
||||
// status: 'invited',
|
||||
// language: 'en',
|
||||
// updateDate: new Date().toISOString(),
|
||||
// createDate: new Date().toISOString(),
|
||||
// failedLoginAttempts: 0,
|
||||
// userGroup: userGroup,
|
||||
// };
|
||||
// this._users.next([...users, user]);
|
||||
// this.requestUpdate('users');
|
||||
|
||||
//TODO: Send invite email with message
|
||||
return user;
|
||||
}
|
||||
// //TODO: Send invite email with message
|
||||
// return user;
|
||||
// }
|
||||
|
||||
public deleteUser(key: string) {
|
||||
const users = this._users.getValue();
|
||||
const index = users.findIndex((u) => u.key === key);
|
||||
if (index === -1) return;
|
||||
users.splice(index, 1);
|
||||
this._users.next(users);
|
||||
this.requestUpdate('users');
|
||||
}
|
||||
// public deleteUser(key: string) {
|
||||
// const users = this._users.getValue();
|
||||
// const index = users.findIndex((u) => u.key === key);
|
||||
// if (index === -1) return;
|
||||
// users.splice(index, 1);
|
||||
// this._users.next(users);
|
||||
// this.requestUpdate('users');
|
||||
// }
|
||||
|
||||
public getTagLookAndColor(status?: string): { color: InterfaceColor; look: InterfaceLook } {
|
||||
switch ((status || '').toLowerCase()) {
|
||||
|
||||
@@ -5,8 +5,9 @@ import { repeat } from 'lit/directives/repeat.js';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
||||
import { UmbContextConsumerMixin } from '../../../../../../../core/context';
|
||||
import UmbEditorViewUsersElement, { UserItem } from '../../editor-view-users.element';
|
||||
import UmbEditorViewUsersElement from '../../editor-view-users.element';
|
||||
import { UmbUserStore } from '../../../../../../../core/stores/user/user.store';
|
||||
import type { UserEntity } from '../../../../../../../core/models';
|
||||
|
||||
@customElement('umb-editor-view-users-grid')
|
||||
export class UmbEditorViewUsersGridElement extends UmbContextConsumerMixin(LitElement) {
|
||||
@@ -31,7 +32,7 @@ export class UmbEditorViewUsersGridElement extends UmbContextConsumerMixin(LitEl
|
||||
];
|
||||
|
||||
@state()
|
||||
private _users: Array<UserItem> = [];
|
||||
private _users: Array<UserEntity> = [];
|
||||
|
||||
@state()
|
||||
private _selection: Array<string> = [];
|
||||
@@ -85,15 +86,15 @@ export class UmbEditorViewUsersGridElement extends UmbContextConsumerMixin(LitEl
|
||||
history.pushState(null, '', '/section/users/view/users/details' + '/' + key); //TODO Change to a tag with href and make dynamic
|
||||
}
|
||||
|
||||
private _selectRowHandler(user: UserItem) {
|
||||
private _selectRowHandler(user: UserEntity) {
|
||||
this._usersContext?.select(user.key);
|
||||
}
|
||||
|
||||
private _deselectRowHandler(user: UserItem) {
|
||||
private _deselectRowHandler(user: UserEntity) {
|
||||
this._usersContext?.deselect(user.key);
|
||||
}
|
||||
|
||||
private renderUserCard(user: UserItem) {
|
||||
private renderUserCard(user: UserEntity) {
|
||||
if (!this._userStore) return;
|
||||
|
||||
const statusLook = this._usersContext?.getTagLookAndColor(user.status ? user.status : '');
|
||||
|
||||
@@ -4,12 +4,13 @@ import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbContextConsumerMixin } from '../../../../../../../core/context';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { Subscription } from 'rxjs';
|
||||
import UmbEditorViewUsersElement, { UserItem } from '../../editor-view-users.element';
|
||||
import UmbEditorViewUsersElement from '../../editor-view-users.element';
|
||||
import { UmbUserStore } from '../../../../../../../core/stores/user/user.store';
|
||||
import type { UserEntity } from '../../../../../../../core/models';
|
||||
|
||||
interface TableColumn {
|
||||
name: string;
|
||||
sort: (items: Array<UserItem>, desc: boolean) => Array<UserItem>;
|
||||
sort: (items: Array<UserEntity>, desc: boolean) => Array<UserEntity>;
|
||||
}
|
||||
|
||||
@customElement('umb-editor-view-users-table')
|
||||
@@ -74,7 +75,7 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE
|
||||
private _sortingDesc = false;
|
||||
|
||||
@state()
|
||||
private _users: Array<UserItem> = [];
|
||||
private _users: Array<UserEntity> = [];
|
||||
|
||||
private _userStore?: UmbUserStore;
|
||||
private _usersContext?: UmbEditorViewUsersElement;
|
||||
@@ -97,7 +98,7 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE
|
||||
this._columns = [
|
||||
{
|
||||
name: 'Name',
|
||||
sort: (items: Array<UserItem>, desc: boolean) => {
|
||||
sort: (items: Array<UserEntity>, desc: boolean) => {
|
||||
return desc
|
||||
? [...items].sort((a, b) => b.name.localeCompare(a.name))
|
||||
: [...items].sort((a, b) => a.name.localeCompare(b.name));
|
||||
@@ -105,7 +106,7 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE
|
||||
},
|
||||
{
|
||||
name: 'User group',
|
||||
sort: (items: Array<UserItem>, desc: boolean) => {
|
||||
sort: (items: Array<UserEntity>, desc: boolean) => {
|
||||
return desc
|
||||
? [...items].sort((a, b) => b.name.localeCompare(a.name))
|
||||
: [...items].sort((a, b) => a.name.localeCompare(b.name));
|
||||
@@ -113,7 +114,7 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE
|
||||
},
|
||||
{
|
||||
name: 'Last login',
|
||||
sort: (items: Array<UserItem>, desc: boolean) => {
|
||||
sort: (items: Array<UserEntity>, desc: boolean) => {
|
||||
return desc
|
||||
? [...items].sort((a, b) => +new Date(b.lastLoginDate || 0) - +new Date(a.lastLoginDate || 0))
|
||||
: [...items].sort((a, b) => +new Date(a.lastLoginDate || 0) - +new Date(b.lastLoginDate || 0));
|
||||
@@ -121,7 +122,7 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
sort: (items: Array<UserItem>, desc: boolean) => {
|
||||
sort: (items: Array<UserEntity>, desc: boolean) => {
|
||||
return desc
|
||||
? [...items].sort((a, b) =>
|
||||
b.status && a.status ? b.status.localeCompare(a.status) : (a.status ? 1 : 0) - (b.status ? 1 : 0)
|
||||
@@ -165,11 +166,11 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE
|
||||
history.pushState(null, '', '/section/users/view/users/details' + '/' + key); //TODO: make a tag with href
|
||||
}
|
||||
|
||||
private _selectRowHandler(user: UserItem) {
|
||||
private _selectRowHandler(user: UserEntity) {
|
||||
this._usersContext?.select(user.key);
|
||||
}
|
||||
|
||||
private _deselectRowHandler(user: UserItem) {
|
||||
private _deselectRowHandler(user: UserEntity) {
|
||||
this._usersContext?.deselect(user.key);
|
||||
}
|
||||
|
||||
@@ -195,7 +196,7 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE
|
||||
`;
|
||||
}
|
||||
|
||||
protected renderRowTemplate = (user: UserItem) => {
|
||||
protected renderRowTemplate = (user: UserEntity) => {
|
||||
if (!this._usersContext) return;
|
||||
|
||||
const statusLook = this._usersContext.getTagLookAndColor(user.status ? user.status : '');
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
import type { components } from '../../../schemas/generated-schema';
|
||||
import { Entity } from '../../mocks/data/entities';
|
||||
|
||||
export type PostInstallRequest = components['schemas']['InstallSetupRequest'];
|
||||
export type StatusResponse = components['schemas']['StatusResponse'];
|
||||
@@ -55,3 +56,21 @@ export type ManifestElementType =
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type HTMLElementConstructor<T = HTMLElement> = new (...args: any[]) => T;
|
||||
|
||||
// Users
|
||||
export interface UserEntity extends Entity {
|
||||
type: 'user';
|
||||
}
|
||||
|
||||
export interface UserDetails extends UserEntity {
|
||||
email: string;
|
||||
status: string;
|
||||
language: string;
|
||||
lastLoginDate?: string;
|
||||
lastLockoutDate?: string;
|
||||
lastPasswordChangeDate?: string;
|
||||
updateDate: string;
|
||||
createDate: string;
|
||||
failedLoginAttempts: number;
|
||||
userGroup?: string; //TODO Implement this
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { UserItem } from '../../../backoffice/editors/users/views/users/editor-view-users.element';
|
||||
import type { UserEntity } from '../../models';
|
||||
import { UmbEntityStore } from '../entity.store';
|
||||
import { UmbDataStoreBase } from '../store';
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbUserStore
|
||||
* @extends {UmbDataStoreBase<UserItem>}
|
||||
* @extends {UmbDataStoreBase<UserEntity>}
|
||||
* @description - Data Store for Users
|
||||
*/
|
||||
export class UmbUserStore extends UmbDataStoreBase<UserItem> {
|
||||
export class UmbUserStore extends UmbDataStoreBase<UserEntity> {
|
||||
private _entityStore: UmbEntityStore;
|
||||
|
||||
constructor(entityStore: UmbEntityStore) {
|
||||
@@ -17,7 +17,7 @@ export class UmbUserStore extends UmbDataStoreBase<UserItem> {
|
||||
this._entityStore = entityStore;
|
||||
}
|
||||
|
||||
getAll(): Observable<Array<UserItem>> {
|
||||
getAll(): Observable<Array<UserEntity>> {
|
||||
// TODO: use Fetcher API.
|
||||
// TODO: only fetch if the data type is not in the store?
|
||||
fetch(`/umbraco/backoffice/users`)
|
||||
@@ -35,7 +35,7 @@ export class UmbUserStore extends UmbDataStoreBase<UserItem> {
|
||||
* @return {*} {(Observable<DataTypeDetails | null>)}
|
||||
* @memberof UmbDataTypeStore
|
||||
*/
|
||||
getByKey(key: string): Observable<UserItem | null> {
|
||||
getByKey(key: string): Observable<UserEntity | null> {
|
||||
// TODO: use Fetcher API.
|
||||
// TODO: only fetch if the data type is not in the store?
|
||||
fetch(`/umbraco/backoffice/users/${key}`)
|
||||
@@ -46,7 +46,7 @@ export class UmbUserStore extends UmbDataStoreBase<UserItem> {
|
||||
});
|
||||
|
||||
return this.items.pipe(
|
||||
map((dataTypes: Array<UserItem>) => dataTypes.find((node: UserItem) => node.key === key) || null)
|
||||
map((dataTypes: Array<UserEntity>) => dataTypes.find((node: UserEntity) => node.key === key) || null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ export class UmbEntityData<T extends Entity> extends UmbData<T> {
|
||||
super(data);
|
||||
}
|
||||
|
||||
getItems(type = '', parentKey = '') {
|
||||
getItems(type: string, parentKey = '') {
|
||||
if (!type) return [];
|
||||
return entities.filter((item) => item.type === type && item.parentKey === parentKey);
|
||||
return this.data.filter((item) => item.type === type && item.parentKey === parentKey);
|
||||
}
|
||||
|
||||
getByKey(key: string) {
|
||||
|
||||
1778
src/Umbraco.Web.UI.Client/src/mocks/data/users.data.ts
Normal file
1778
src/Umbraco.Web.UI.Client/src/mocks/data/users.data.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
import { rest } from 'msw';
|
||||
import { tempData } from '../../backoffice/editors/users/views/users/tempData';
|
||||
import { umbUsersData } from '../data/users.data';
|
||||
|
||||
// TODO: add schema
|
||||
export const handlers = [
|
||||
rest.get('/umbraco/backoffice/users', (req, res, ctx) => {
|
||||
const response = {
|
||||
items: tempData,
|
||||
items: umbUsersData.getItems('user'),
|
||||
};
|
||||
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
@@ -15,7 +15,7 @@ export const handlers = [
|
||||
const key = req.params.key as string;
|
||||
if (!key) return;
|
||||
|
||||
const user = tempData.find((x) => x.key === key);
|
||||
const user = umbUsersData.getByKey(key);
|
||||
|
||||
return res(ctx.status(200), ctx.json([user]));
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user