Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split reusable content into separated components #853

Merged
merged 45 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
cbbb679
Remove server-related items from side menu
acelaya Jul 15, 2023
d82c0dc
Move stuff belonging to the component to shlink-web-component
acelaya Jul 16, 2023
682de08
Extract initial Shlink logic to ShlinkWebComponent
acelaya Jul 16, 2023
4b2a9ea
Create redux store for shlink-web-component
acelaya Jul 19, 2023
dddbc23
Move mercure module to shlink-web-component
acelaya Jul 23, 2023
b312221
Move settings from store to another context
acelaya Jul 23, 2023
2ac5236
Provide API client to shlink-web-component
acelaya Jul 24, 2023
3fe4877
Allow heallth request to be performed for a different domain
acelaya Jul 24, 2023
5f6dc18
Define Shlink API contract
acelaya Jul 24, 2023
21525ef
Decouple shlink-web-component from the concept of servers
acelaya Jul 24, 2023
768fb19
Remove feature flags for features introduced on Shlink <3.0
acelaya Jul 24, 2023
3a0cea1
Extract shlink-web-component outside of src folder
acelaya Jul 24, 2023
d49da18
Use apiClient factory to dynamically resolved different values at run…
acelaya Jul 26, 2023
0169060
Fix mercure info loading in shlink-web-component
acelaya Jul 27, 2023
275745f
Move some modules from src to shlink-web-component
acelaya Jul 27, 2023
8d24116
Move more components to shlink-web-component when applicable
acelaya Jul 29, 2023
bc11e56
Move date components and helpers to shlink-web-component
acelaya Jul 31, 2023
c73a592
Move more non-shared components to shlink-web-component
acelaya Jul 31, 2023
5ec5396
Decouple shlink-web-component from NotFound component
acelaya Jul 31, 2023
99ce8c9
First shlink-frontend-kit iteration
acelaya Jul 31, 2023
b7d57a5
Move shlink-frontend-kit tests to its own dir
acelaya Aug 2, 2023
c48facc
Create src folder for shlink-web-component
acelaya Aug 2, 2023
c794ff8
Move shlink-web-component tests to their own folder
acelaya Aug 2, 2023
c4d7ac2
Refactor and fix main app tests
acelaya Aug 4, 2023
bdcfcee
Fix incorrect import in shlink-frontend-kit test
acelaya Aug 4, 2023
4d8477a
Fix shlink-web-component tests
acelaya Aug 4, 2023
9f2b0f7
Fix some CSS coding styles
acelaya Aug 4, 2023
93048e3
Add aliases for shlink-web-component and shlink-frontend-kit packages
acelaya Aug 4, 2023
d9939f5
Move theme helpers and some stylesheets to proper locations
acelaya Aug 5, 2023
007d79d
Fix coding styles
acelaya Aug 5, 2023
9f9f3b6
Fix imports
acelaya Aug 6, 2023
89e7565
Delegate tag color storage to ShlinkWebComponent consuming app
acelaya Aug 6, 2023
75fed53
Add test for TagColorsStorage
acelaya Aug 6, 2023
c3b6ce3
Fix remaining dependencies from shlink-web-component into main app
acelaya Aug 6, 2023
5a9640b
Remove sidebar reducer, which couple web-client with web-component
acelaya Aug 6, 2023
47dd105
Make sure props are not passed to Fragment
acelaya Aug 6, 2023
23daa2d
Add Shlink prefix to api-contract models
acelaya Aug 6, 2023
d97db9e
Moved some types from short-url/data to api-contract
acelaya Aug 7, 2023
f16f51a
Move all relevant API types to api-contract
acelaya Aug 7, 2023
3045586
Fix ShortUrlForm test
acelaya Aug 7, 2023
914efc6
Relocate stylesheets to their proper component
acelaya Aug 7, 2023
8deccea
Move bootstrap overrides to shlink-frontend-kit
acelaya Aug 7, 2023
74aaed6
Fix styles import order
acelaya Aug 7, 2023
6db60f0
Create ShlinkWebComponent test
acelaya Aug 7, 2023
a2f3673
Mute CSS style rule
acelaya Aug 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"license": "MIT",
"scripts": {
"lint": "npm run lint:css && npm run lint:js",
"lint:css": "stylelint src/*.scss src/**/*.scss",
"lint:js": "eslint --ext .js,.ts,.tsx src test",
"lint:css": "stylelint src/*.scss src/**/*.scss shlink-web-component/*.scss shlink-web-component/**/*.scss shlink-frontend-kit/*.scss shlink-frontend-kit/**/*.scss",
"lint:js": "eslint --ext .js,.ts,.tsx src shlink-web-component shlink-frontend-kit test",
"lint:fix": "npm run lint:css:fix && npm run lint:js:fix",
"lint:css:fix": "npm run lint:css -- --fix",
"lint:js:fix": "npm run lint:js -- --fix",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import type { ReactNode } from 'react';
import type { CardProps } from 'reactstrap';
import { Card, CardBody, CardHeader } from 'reactstrap';

interface SimpleCardProps extends Omit<CardProps, 'title'> {
export type SimpleCardProps = Omit<CardProps, 'title'> & {
title?: ReactNode;
bodyClassName?: string;
}
};

export const SimpleCard = ({ title, children, bodyClassName, ...rest }: SimpleCardProps) => (
<Card {...rest}>
Expand Down
3 changes: 3 additions & 0 deletions shlink-frontend-kit/src/block/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './Message';
export * from './Result';
export * from './SimpleCard';
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import classNames from 'classnames';
import { identity } from 'ramda';
import type { ChangeEvent, FC, PropsWithChildren } from 'react';
import { useDomId } from './helpers/hooks';
import { useDomId } from '../hooks';

export type BooleanControlProps = PropsWithChildren<{
checked?: boolean;
Expand All @@ -10,9 +10,9 @@ export type BooleanControlProps = PropsWithChildren<{
inline?: boolean;
}>;

interface BooleanControlWithTypeProps extends BooleanControlProps {
type BooleanControlWithTypeProps = BooleanControlProps & {
type: 'switch' | 'checkbox';
}
};

export const BooleanControl: FC<BooleanControlWithTypeProps> = (
{ checked = false, onChange = identity, className, children, type, inline = false },
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { FC, PropsWithChildren } from 'react';
import type { InputType } from 'reactstrap/types/lib/Input';
import { useDomId } from '../helpers/hooks';
import { useDomId } from '../hooks';
import { LabeledFormGroup } from './LabeledFormGroup';

export type InputFormGroupProps = PropsWithChildren<{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import '../utils/mixins/vertical-align';
@import '../../../shlink-web-component/src/utils/mixins/vertical-align';

.search-field {
position: relative;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import './SearchField.scss';
const DEFAULT_SEARCH_INTERVAL = 500;
let timer: NodeJS.Timeout | null;

interface SearchFieldProps {
type SearchFieldProps = {
onChange: (value: string) => void;
className?: string;
large?: boolean;
noBorder?: boolean;
initialValue?: string;
}
};

export const SearchField = ({ onChange, className, large = true, noBorder = false, initialValue = '' }: SearchFieldProps) => {
const [searchTerm, setSearchTerm] = useState(initialValue);
Expand Down
5 changes: 5 additions & 0 deletions shlink-frontend-kit/src/form/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './Checkbox';
export * from './ToggleSwitch';
export * from './InputFormGroup';
export * from './LabeledFormGroup';
export * from './SearchField';
16 changes: 16 additions & 0 deletions shlink-frontend-kit/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useRef, useState } from 'react';
import { v4 as uuid } from 'uuid';

type ToggleResult = [boolean, () => void, () => void, () => void];

export const useToggle = (initialValue = false): ToggleResult => {
const [flag, setFlag] = useState<boolean>(initialValue);
return [flag, () => setFlag(!flag), () => setFlag(true), () => setFlag(false)];
};

export const useDomId = (): string => {
const { current: id } = useRef(`dom-${uuid()}`);
return id;
};

export const useElementRef = <T>() => useRef<T | null>(null);
219 changes: 219 additions & 0 deletions shlink-frontend-kit/src/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
@import './utils/ResponsiveTable';
@import './theme/theme';

/* stylelint-disable no-descending-specificity */

a,
.btn-link {
text-decoration: none;
}

/* stylelint-disable-next-line selector-max-pseudo-class */
a:not(.nav-link):not(.navbar-brand):not(.page-link):not(.highlight-card):not(.btn):not(.dropdown-item):hover,
.btn-link:hover {
text-decoration: underline;
}

.bg-main {
background-color: $mainColor !important;
}

.bg-warning {
color: $lightTextColor;
}

.card-body,
.card-header,
.list-group-item {
background-color: transparent;
}

.card-footer {
background-color: var(--primary-color-alfa);
}

.card {
box-shadow: 0 .125rem .25rem rgb(0 0 0 / .075);
background-color: var(--primary-color);
border-color: var(--border-color);
}

.list-group {
background-color: var(--primary-color);
}

.modal-content,
.page-link,
.page-item.disabled .page-link,
.dropdown-menu {
background-color: var(--primary-color);
}

.modal-header,
.modal-footer,
.card-header,
.card-footer,
.table thead th,
.table th,
.table td,
.page-link,
.page-link:hover,
.page-item.disabled .page-link,
.dropdown-divider,
.dropdown-menu,
.list-group-item,
.modal-content,
hr {
border-color: var(--border-color);
}

.table-bordered,
.table-bordered thead th,
.table-bordered thead td {
border-color: var(--table-border-color);
}

.page-link:hover,
.page-link:focus {
background-color: var(--secondary-color);
}

.page-item.active .page-link {
background-color: var(--brand-color);
border-color: var(--brand-color);
}

.pagination .page-link {
cursor: pointer;
}

.container-xl {
@media (min-width: $xlgMin) {
max-width: 1320px;
}

@media (max-width: $smMax) {
padding-right: 0;
padding-left: 0;
}
}

/* Deprecated. Brought from bootstrap 4 */
.btn-block {
display: block;
width: 100%;
}

.btn-primary,
.btn-primary:hover,
.btn-primary:active,
.btn-primary.active,
.btn-outline-primary:hover,
.btn-outline-primary:active,
.btn-outline-primary.active, {
color: #ffffff;
}

.dropdown-item,
.dropdown-item-text {
color: var(--text-color);
}

.dropdown-item:not(:disabled) {
cursor: pointer;
}

.dropdown-item:focus:not(:disabled),
.dropdown-item:hover:not(:disabled),
.dropdown-item.active:not(:disabled),
.dropdown-item:active:not(:disabled) {
background-color: var(--active-color) !important;
color: var(--text-color) !important;
}

.dropdown-item--danger.dropdown-item--danger {
color: $dangerColor;

&:hover,
&:active,
&.active {
color: $dangerColor !important;
}
}

.badge-main {
color: #ffffff;
background-color: var(--brand-color);
}

.close,
.close:hover,
.table,
.table-hover > tbody > tr:hover > *,
.table-hover > tbody > tr > * {
color: var(--text-color);
}

.btn-close {
filter: var(--btn-close-filter);
}

.table-hover tbody tr:hover {
background-color: var(--secondary-color);
}

.form-control,
.form-control:focus {
background-color: var(--primary-color);
border-color: var(--input-border-color);
color: var(--input-text-color);
}

.form-control.disabled,
.form-control:disabled {
background-color: var(--input-disabled-color);
cursor: not-allowed;
}

.card .form-control:not(:disabled),
.card .form-control:not(:disabled):hover {
background-color: var(--input-color);
}

.table-active,
.table-active > th,
.table-active > td {
background-color: var(--table-highlight-color) !important;
}

.navbar-brand {
@media (max-width: $smMax) {
margin: 0 auto !important;
}
}

.indivisible {
white-space: nowrap;
}

.pointer {
cursor: pointer;
}

.progress-bar {
background-color: $mainColor;
}

.btn-xs-block {
@media (max-width: $xsMax) {
width: 100%;
display: block;
}
}

.btn-md-block {
@media (max-width: $mdMax) {
width: 100%;
display: block;
}
}
7 changes: 7 additions & 0 deletions shlink-frontend-kit/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from './block';
export * from './form';
export * from './hooks';
export * from './navigation';
export * from './ordering';
export * from './theme';
export * from './utils';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* stylelint-disable no-descending-specificity */

@import '../utils/mixins/vertical-align';
@import '../../../shlink-web-component/src/utils/mixins/vertical-align';

.dropdown-btn__toggle.dropdown-btn__toggle {
text-align: left;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import classNames from 'classnames';
import type { FC, PropsWithChildren, ReactNode } from 'react';
import { Dropdown, DropdownMenu, DropdownToggle } from 'reactstrap';
import type { DropdownToggleProps } from 'reactstrap/types/lib/DropdownToggle';
import { useToggle } from './helpers/hooks';
import { useToggle } from '../hooks';
import './DropdownBtn.scss';

export type DropdownBtnProps = PropsWithChildren<Omit<DropdownToggleProps, 'caret' | 'size' | 'outline'> & {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import './base';
@import '../base';

.nav-pills__nav {
position: sticky !important;
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions shlink-frontend-kit/src/navigation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './DropdownBtn';
export * from './RowDropdownBtn';
export * from './NavPills';
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import { toPairs } from 'ramda';
import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from 'reactstrap';
import type { Order, OrderDir } from './helpers/ordering';
import { determineOrderDir } from './helpers/ordering';
import type { Order, OrderDir } from './ordering';
import { determineOrderDir } from './ordering';
import './OrderingDropdown.scss';

export interface OrderingDropdownProps<T extends string = string> {
export type OrderingDropdownProps<T extends string = string> = {
items: Record<T, string>;
order: Order<T>;
onChange: (orderField?: T, orderDir?: OrderDir) => void;
isButton?: boolean;
right?: boolean;
prefixed?: boolean;
}
};

export function OrderingDropdown<T extends string = string>(
{ items, order, onChange, isButton = true, right = false, prefixed = true }: OrderingDropdownProps<T>,
Expand Down
2 changes: 2 additions & 0 deletions shlink-frontend-kit/src/ordering/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './ordering';
export * from './OrderingDropdown';
Loading