e7527081b4
Add the "binder" section (?page=binder&projectId=): links a SharePoint project to the TNSU API project catalogue by writing UniqueId0/UniqueName to the "Проекты" list. The class component is rewritten as function components with hooks while keeping the legacy behaviour and texts: the same project GET with odata=nometadata and empty odata-version, MERGE with IF-MATCH * for bind/unbind (no confirmation), catalogue search with 400 ms debounce and 20-per-page paging, card select/deselect, status colours, ru-RU dates and HTML-entity decoding of the address. Fluent UI is replaced with ui-kit. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
248 lines
4.0 KiB
SCSS
248 lines
4.0 KiB
SCSS
@import '../../../../styles/design-tokens';
|
|
|
|
// Толщина акцентных полос карточек — как в binder.
|
|
$accent-bar-width: 3px;
|
|
$accent-line-height: 2px;
|
|
// На самых узких экранах карточки компактнее — точка перелома из binder (между $bp-xs и $bp-sm).
|
|
$compact-card-bp: 480px;
|
|
|
|
.page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $sp-4;
|
|
width: 100%;
|
|
}
|
|
|
|
.dismissibleAlert {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: $sp-2;
|
|
}
|
|
|
|
.dismissibleAlertBody {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.hairline {
|
|
@include hairline;
|
|
margin: 0;
|
|
}
|
|
|
|
// ---- Карточка проекта SharePoint ----
|
|
|
|
.projectCard {
|
|
position: relative;
|
|
overflow: hidden;
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
padding: $sp-6 $sp-7;
|
|
background: $white;
|
|
border: 1px solid $gray-200;
|
|
border-radius: $r-lg;
|
|
box-shadow: $sh-2;
|
|
|
|
// Navy-линия сверху.
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: $accent-line-height;
|
|
background: linear-gradient(90deg, $navy-800, $navy-600 60%, transparent);
|
|
}
|
|
|
|
// Золотая полоса слева.
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: $accent-bar-width;
|
|
background: $grad-gold-v;
|
|
}
|
|
}
|
|
|
|
.projectTitle {
|
|
margin: 0;
|
|
font-family: $font-serif;
|
|
font-size: $fs-form-title;
|
|
font-weight: 600;
|
|
color: $navy-900;
|
|
overflow-wrap: break-word;
|
|
}
|
|
|
|
.projectFields {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: $sp-1 $sp-4;
|
|
margin-top: $sp-3;
|
|
}
|
|
|
|
.fieldLine {
|
|
min-width: 0;
|
|
font-size: $fs-label;
|
|
color: $gray-500;
|
|
overflow-wrap: break-word;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.fieldLabel {
|
|
font-weight: 600;
|
|
color: $gray-700;
|
|
}
|
|
|
|
.bindingRow {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: $sp-2;
|
|
margin-top: $sp-3;
|
|
padding-top: $sp-3;
|
|
border-top: 1px solid $gray-200;
|
|
}
|
|
|
|
.boundInfo {
|
|
flex: 1;
|
|
min-width: 0;
|
|
font-size: $fs-label;
|
|
color: $gray-500;
|
|
overflow-wrap: break-word;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.unbindAction {
|
|
margin-top: $sp-2;
|
|
}
|
|
|
|
// ---- Поиск по справочнику ----
|
|
|
|
.sectionTitle {
|
|
margin: 0;
|
|
font-family: $font-serif;
|
|
font-size: $fs-section-title;
|
|
font-weight: 600;
|
|
color: $navy-900;
|
|
}
|
|
|
|
.searchBox {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: $sp-1;
|
|
}
|
|
|
|
.searchInput {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.emptyResults {
|
|
display: block;
|
|
padding: $sp-4 0;
|
|
font-size: $fs-label;
|
|
text-align: center;
|
|
color: $gray-400;
|
|
}
|
|
|
|
.results {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $sp-2;
|
|
}
|
|
|
|
.resultItem {
|
|
position: relative;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $sp-1;
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
padding: $sp-3 $sp-4;
|
|
background: $white;
|
|
border: 1px solid $gray-200;
|
|
border-radius: $r-md;
|
|
box-shadow: $sh-1;
|
|
cursor: pointer;
|
|
transition: 0.22s;
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: $accent-bar-width;
|
|
background: $grad-gold-v;
|
|
opacity: 0;
|
|
transition: 0.22s;
|
|
}
|
|
|
|
&:hover {
|
|
box-shadow: $sh-3;
|
|
transform: translateY(-2px);
|
|
border-color: transparent;
|
|
|
|
&::before {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.resultItemSelected {
|
|
background: $gold-50;
|
|
border-color: $gold-400;
|
|
|
|
&::before {
|
|
opacity: 1;
|
|
}
|
|
|
|
&:hover {
|
|
background: $gold-50;
|
|
border-color: $gold-400;
|
|
}
|
|
}
|
|
|
|
.resultName {
|
|
font-size: $fs-body;
|
|
font-weight: 600;
|
|
color: $navy-900;
|
|
overflow-wrap: break-word;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.bindAction {
|
|
margin-top: $sp-1;
|
|
}
|
|
|
|
.pagination {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: $sp-2;
|
|
}
|
|
|
|
.pageInfo {
|
|
font-size: $fs-label;
|
|
color: $gray-500;
|
|
}
|
|
|
|
@include below($bp-sm) {
|
|
.projectFields {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
@include below($compact-card-bp) {
|
|
.projectCard {
|
|
padding: $sp-3 $sp-4;
|
|
}
|
|
|
|
.resultItem {
|
|
padding: $sp-2 $sp-3;
|
|
}
|
|
}
|