WeddingThankYou 1.0.0.0
결혼식 이후 감사 인사와 사진, 계좌 안내, 연락처를 모바일 페이지로 전달하는 감사장 서비스입니다.
로딩중...
검색중...
일치하는것 없음
WeddingThankYou.ViewModels.AdminViewModel 클래스 참조sealed
WeddingThankYou.ViewModels.AdminViewModel에 대한 협력 다이어그램:

Public 멤버 함수

 AdminViewModel (ITenantStore tenants, IPhotoService photos, WeddingOptions opts, ThankYouUserContext userContext, IMediaQuotaPolicyResolver mediaPolicyResolver, ISuperAdminSessionTokenService superAdminTokens)
void SetStatusMessage (string message)
async Task InitializeAsync (string slug, CancellationToken ct=default)
async Task< bool > LoginAsync (string slug, CancellationToken ct=default)
async Task< bool > LoginAsSuperAdminAsync (string slug, string? sessionToken, CancellationToken ct=default)
async Task LoadAsync (string slug, CancellationToken ct=default)
async Task SaveConfigAsync (CancellationToken ct=default)
async Task SaveStoryChapterAsync (StoryChapter chapter, CancellationToken ct=default)
async Task AddStoryChapterAsync (CancellationToken ct=default)
async Task DeleteStoryChapterAsync (int chapterNumber, CancellationToken ct=default)
async Task RemoveAdminAsync (string userId, CancellationToken ct=default)
async Task UploadGalleryAsync (string slug, IBrowserFile file, CancellationToken ct=default)
async Task UploadHeroAsync (string slug, IBrowserFile file, CancellationToken ct=default)
async Task DeletePhotoAsync (string slug, string fileName, CancellationToken ct=default)
async Task MoveGalleryPhotoAsync (string fileName, int offset, CancellationToken ct=default)
async Task MoveGalleryPhotoToAsync (string fileName, bool first, CancellationToken ct=default)
async Task UploadRoadMapAsync (string slug, IBrowserFile file, CancellationToken ct=default)
async Task GeocodeAsync (CancellationToken ct=default)
void GenerateMapLinks ()
string GetThumbUrl (string slug, string fileName)
string GetPhotoUrl (string slug, string fileName)
string GetHeroUrl (string slug, string fileName)
string GetRoadMapUrl (string slug, string fileName)
string GetMusicUrl (string slug, string fileName)
string GetOgImageUrl (string slug, string fileName)
string GetVideoUrl (string slug, string fileName)
async Task UploadOgImageAsync (string slug, IBrowserFile file, CancellationToken ct=default)
async Task UploadVideoAsync (string slug, IBrowserFile file, CancellationToken ct=default)
async Task DeleteVideoAsync (string slug, string fileName, CancellationToken ct=default)
async Task UploadMusicAsync (string slug, IBrowserFile file, CancellationToken ct=default)

속성

string MaxVideoSizeLabel = "최대 200MB" [get, private set]
int MaxVideoCount = 6 [get, private set]
EffectiveMediaPolicy? EffectiveMediaPolicy [get, private set]
TenantConfigConfig [get, private set]
IReadOnlyList< PhotoInfoGallery = [] [get, private set]
bool IsLoaded [get, private set]
bool IsAuthenticated [get, private set]
bool IsSignedIn [get, private set]
bool IsLinkedToCurrentUser [get, private set]
bool IsOwner [get, private set]
IReadOnlyList< ThankYouAdminUserEffectiveAdminUsers = [] [get, private set]
string StatusMessage = "" [get, private set]
string CurrentUserLabel = "" [get, private set]
bool IsUploading [get, private set]
bool IsGeocoding [get, private set]
string GeocodeStatus = "" [get, private set]
string LoginPassword = "" [get, set]

Private 멤버 함수

async Task RefreshCurrentUserAsync ()
bool ValidateLayoutForSave (TenantConfig config)
bool ValidateThemeForSave (TenantConfig config)
void NormalizeGalleryFileOrder ()

정적 Private 멤버 함수

static List< ThankYouAdminUserGetAdminUsers (TenantConfig config)
static bool IsOwnerUser (TenantConfig config, ThankYouCurrentUser user)
static bool IsAdminUser (TenantConfig config, ThankYouCurrentUser user)
static void EnsureAdminUser (TenantConfig config, ThankYouCurrentUser user, string role)
static IReadOnlyList< ThankYouAdminUserBuildEffectiveAdminUsers (TenantConfig config)

Private 속성

readonly ITenantStore _tenants
readonly IPhotoService _photos
readonly WeddingOptions _opts
readonly ThankYouUserContext _userContext
readonly IMediaQuotaPolicyResolver _mediaPolicyResolver
readonly ISuperAdminSessionTokenService _superAdminTokens

정적 Private 속성

static readonly HttpClient _geocodeHttp

상세한 설명

AdminViewModel.cs 파일의 20 번째 라인에서 정의되었습니다.

생성자 & 소멸자 문서화

◆ AdminViewModel()

WeddingThankYou.ViewModels.AdminViewModel.AdminViewModel ( ITenantStore tenants,
IPhotoService photos,
WeddingOptions opts,
ThankYouUserContext userContext,
IMediaQuotaPolicyResolver mediaPolicyResolver,
ISuperAdminSessionTokenService superAdminTokens )
inline

지정한 설정으로 AdminViewModel 클래스의 새 인스턴스를 초기화합니다.

매개변수
tenantstenants에 사용할 ITenantStore 값입니다.
photosphotos에 사용할 IPhotoService 값입니다.
optsopts에 사용할 WeddingOptions 값입니다.
userContextuser Context에 사용할 ThankYouUserContext 값입니다.
mediaPolicyResolvermedia Policy Resolver에 사용할 IMediaQuotaPolicyResolver 값입니다.
superAdminTokenssuper Admin Tokens에 사용할 ISuperAdminSessionTokenService 값입니다.

AdminViewModel.cs 파일의 146 번째 라인에서 정의되었습니다.

153 {
154 _tenants = tenants;
155 _photos = photos;
156 _opts = opts;
157 _userContext = userContext;
158 _mediaPolicyResolver = mediaPolicyResolver;
159 _superAdminTokens = superAdminTokens;
160 }

다음을 참조함 : _mediaPolicyResolver, _opts, _photos, _superAdminTokens, _tenants, _userContext.

멤버 함수 문서화

◆ AddStoryChapterAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.AddStoryChapterAsync ( CancellationToken ct = default)
inline

Story Chapter Async 항목을 추가합니다.

매개변수
ct취소 요청을 감시하는 토큰입니다.
반환값
Add Story Chapter Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 772 번째 라인에서 정의되었습니다.

773 {
774 if (Config is null) return;
775 try
776 {
777 ThankYouDesignCatalog.Normalize(Config);
778 var chapters = Config.StoryChapters;
779 var nextNumber = chapters.Count == 0 ? 1 : chapters.Max(x => x.ChapterNumber) + 1;
780 chapters.Add(new StoryChapter
781 {
782 ChapterNumber = nextNumber,
783 Label = $"CHAPTER {nextNumber:00}",
784 Title = "새로운 이야기",
785 });
786
787 await _tenants.SaveAsync(Config, ct).ConfigureAwait(false);
788 StatusMessage = $"CHAPTER {nextNumber:00} 챕터가 추가되었습니다.";
789 }
790 catch (Exception ex)
791 {
792 StatusMessage = $"챕터 추가 오류: {ex.Message}";
793 }
794 }

다음을 참조함 : _tenants, Config, WeddingThankYou.Models.ThankYouDesignCatalog.Normalize(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ BuildEffectiveAdminUsers()

IReadOnlyList< ThankYouAdminUser > WeddingThankYou.ViewModels.AdminViewModel.BuildEffectiveAdminUsers ( TenantConfig config)
inlinestaticprivate

Effective Admin Users 값을 구성합니다.

매개변수
configconfig에 사용할 TenantConfig 값입니다.
반환값
Build Effective Admin Users 작업에서 생성한 IReadOnlyList<ThankYouAdminUser> 결과입니다.

AdminViewModel.cs 파일의 2123 번째 라인에서 정의되었습니다.

2124 {
2125 var users = GetAdminUsers(config);
2126 if (!string.IsNullOrWhiteSpace(config.OwnerUserId) &&
2127 users.All(x => !string.Equals(x.UserId, config.OwnerUserId, StringComparison.Ordinal)))
2128 {
2129 users.Insert(0, new ThankYouAdminUser
2130 {
2131 UserId = config.OwnerUserId,
2132 Provider = config.OwnerProvider,
2133 Email = config.OwnerEmail,
2134 DisplayName = config.OwnerDisplayName,
2135 Role = "Owner",
2136 AddedAt = config.OwnerLinkedAt ?? config.CreatedAt
2137 });
2138 }
2139
2140 foreach (var user in users.Where(x => string.Equals(x.UserId, config.OwnerUserId, StringComparison.Ordinal)))
2141 {
2142 user.Role = "Owner";
2143 }
2144
2145 return users
2146 .OrderByDescending(x => string.Equals(x.Role, "Owner", StringComparison.OrdinalIgnoreCase))
2147 .ThenBy(x => x.AddedAt)
2148 .ToList();
2149 }

다음을 참조함 : GetAdminUsers(), WeddingThankYou.Models.TenantConfig.OwnerDisplayName, WeddingThankYou.Models.TenantConfig.OwnerEmail, WeddingThankYou.Models.TenantConfig.OwnerProvider, WeddingThankYou.Models.TenantConfig.OwnerUserId.

다음에 의해서 참조됨 : InitializeAsync(), LoadAsync(), LoginAsSuperAdminAsync(), LoginAsync(), RemoveAdminAsync(), SaveConfigAsync().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ DeletePhotoAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.DeletePhotoAsync ( string slug,
string fileName,
CancellationToken ct = default )
inline

Delete Photo Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Delete Photo Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1194 번째 라인에서 정의되었습니다.

1195 {
1196 try
1197 {
1198 await _photos.DeleteAsync(slug, fileName, ct).ConfigureAwait(false);
1199 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1200 Gallery = await _photos.GetGalleryAsync(slug, ct).ConfigureAwait(false);
1201 StatusMessage = "삭제 완료";
1202 }
1203 catch (Exception ex) { StatusMessage = $"삭제 오류: {ex.Message}"; }
1204 }

다음을 참조함 : _photos, _tenants, Config, Gallery, StatusMessage.

◆ DeleteStoryChapterAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.DeleteStoryChapterAsync ( int chapterNumber,
CancellationToken ct = default )
inline

Delete Story Chapter Async 작업을 수행합니다.

매개변수
chapterNumberchapter Number에 사용할 int 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Delete Story Chapter Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 828 번째 라인에서 정의되었습니다.

829 {
830 if (Config is null) return;
831 try
832 {
833 ThankYouDesignCatalog.Normalize(Config);
834 if (chapterNumber <= 4)
835 {
836 StatusMessage = "기본 4개 챕터는 유지됩니다.";
837 return;
838 }
839
840 var removed = Config.StoryChapters.RemoveAll(x => x.ChapterNumber == chapterNumber);
841 if (removed == 0)
842 {
843 StatusMessage = "삭제할 챕터를 찾을 수 없습니다.";
844 return;
845 }
846
847 await _tenants.SaveAsync(Config, ct).ConfigureAwait(false);
848 StatusMessage = $"CHAPTER {chapterNumber:00} 챕터가 삭제되었습니다.";
849 }
850 catch (Exception ex)
851 {
852 StatusMessage = $"챕터 삭제 오류: {ex.Message}";
853 }
854 }

다음을 참조함 : _tenants, Config, WeddingThankYou.Models.ThankYouDesignCatalog.Normalize(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ DeleteVideoAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.DeleteVideoAsync ( string slug,
string fileName,
CancellationToken ct = default )
inline

Delete Video Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Delete Video Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1872 번째 라인에서 정의되었습니다.

1873 {
1874 try
1875 {
1876 await _photos.DeleteVideoAsync(slug, fileName, ct).ConfigureAwait(false);
1877 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1878 StatusMessage = "동영상 삭제 완료";
1879 }
1880 catch (Exception ex) { StatusMessage = $"동영상 삭제 오류: {ex.Message}"; }
1881 }

다음을 참조함 : _photos, _tenants, Config, StatusMessage.

◆ EnsureAdminUser()

void WeddingThankYou.ViewModels.AdminViewModel.EnsureAdminUser ( TenantConfig config,
ThankYouCurrentUser user,
string role )
inlinestaticprivate

Ensure Admin User 작업을 수행합니다.

매개변수
configconfig에 사용할 TenantConfig 값입니다.
useruser에 사용할 ThankYouCurrentUser 값입니다.
rolerole에 사용할 string 값입니다.

AdminViewModel.cs 파일의 2070 번째 라인에서 정의되었습니다.

2071 {
2072 if (!user.IsAuthenticated) return;
2073
2074 var users = GetAdminUsers(config);
2075 var existing = users.FirstOrDefault(x => string.Equals(x.UserId, user.Id, StringComparison.Ordinal));
2076 if (existing is null)
2077 {
2078 users.Add(new ThankYouAdminUser
2079 {
2080 UserId = user.Id,
2081 Provider = user.Provider,
2082 Email = user.Email,
2083 DisplayName = user.DisplayName,
2084 Role = role,
2085 AddedAt = DateTime.Now
2086 });
2087 return;
2088 }
2089
2090 existing.Provider = user.Provider;
2091 existing.Email = user.Email;
2092 existing.DisplayName = user.DisplayName;
2093 if (role == "Owner")
2094 {
2095 existing.Role = "Owner";
2096 }
2097 }

다음을 참조함 : GetAdminUsers(), WeddingThankYou.Services.ThankYouCurrentUser().

다음에 의해서 참조됨 : LoginAsync().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GenerateMapLinks()

void WeddingThankYou.ViewModels.AdminViewModel.GenerateMapLinks ( )
inline

Generate Map Links 작업을 수행합니다.

AdminViewModel.cs 파일의 1462 번째 라인에서 정의되었습니다.

1463 {
1464 if (Config is null) return;
1465
1466 var name = Uri.EscapeDataString(Config.VenueName);
1467 var addr = Uri.EscapeDataString(
1468 string.IsNullOrWhiteSpace(Config.VenueAddress) ? Config.VenueName : Config.VenueAddress);
1469 var lat = Config.VenueLat;
1470 var lng = Config.VenueLng;
1471 bool hasCoords = lat != 0 && lng != 0;
1472 var latS = lat.ToString(System.Globalization.CultureInfo.InvariantCulture);
1473 var lngS = lng.ToString(System.Globalization.CultureInfo.InvariantCulture);
1474
1475 // 카카오맵 — 좌표 있으면 핀, 없으면 검색
1476 Config.MapLinkKakao = hasCoords
1477 ? $"https://map.kakao.com/link/map/{name},{latS},{lngS}"
1478 : $"https://map.kakao.com/link/search/{addr}";
1479
1480 // 네이버지도 — 좌표 있으면 좌표 검색, 없으면 주소 검색
1481 Config.MapLinkNaver = hasCoords
1482 ? $"https://map.naver.com/v5/search/{addr}?c={lngS},{latS},15,0,0,0,dh"
1483 : $"https://map.naver.com/v5/search/{addr}";
1484
1485 // 아틀란
1486 if (!string.IsNullOrWhiteSpace(_opts.AtlanAuthKey) && hasCoords)
1487 Config.MapLinkAtlan = $"http://m.atlan.co.kr/searchPlus/linkAtlan.do?shareType=kakao&coordX={lngS}&coordY={latS}&title={name}&AuthKey={_opts.AtlanAuthKey}";
1488
1489 // T맵
1490 if (!string.IsNullOrWhiteSpace(_opts.TmapAppKey) && hasCoords)
1491 Config.MapLinkTmap = $"https://apis.openapi.sk.com/tmap/app/routes?appKey={_opts.TmapAppKey}&name={name}&lon={lngS}&lat={latS}";
1492 }

다음을 참조함 : _opts, Config.

◆ GeocodeAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.GeocodeAsync ( CancellationToken ct = default)
inline

Geocode Async 작업을 수행합니다.

매개변수
ct취소 요청을 감시하는 토큰입니다.
반환값
Geocode Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1428 번째 라인에서 정의되었습니다.

1429 {
1430 if (Config is null) return;
1431 var query = string.IsNullOrWhiteSpace(Config.VenueAddress) ? Config.VenueName : Config.VenueAddress;
1432 if (string.IsNullOrWhiteSpace(query)) { GeocodeStatus = "❗ 예식장 이름 또는 주소를 먼저 입력해주세요."; return; }
1433
1434 IsGeocoding = true;
1435 GeocodeStatus = "";
1436 try
1437 {
1438 var url = $"https://nominatim.openstreetmap.org/search?q={Uri.EscapeDataString(query)}&format=json&limit=1&accept-language=ko";
1439 var results = await _geocodeHttp.GetFromJsonAsync<JsonElement[]>(url, ct).ConfigureAwait(false);
1440 if (results is null || results.Length == 0)
1441 {
1442 GeocodeStatus = "❌ 좌표를 찾을 수 없습니다. 주소를 더 자세히 입력해 보세요.";
1443 return;
1444 }
1445 var item = results[0];
1446 Config.VenueLat = double.Parse(item.GetProperty("lat").GetString()!, System.Globalization.CultureInfo.InvariantCulture);
1447 Config.VenueLng = double.Parse(item.GetProperty("lon").GetString()!, System.Globalization.CultureInfo.InvariantCulture);
1448 GeocodeStatus = $"✅ 좌표 검색 완료 — {item.GetProperty("display_name").GetString()}";
1449 }
1450 catch { GeocodeStatus = "❌ 좌표 검색 중 오류가 발생했습니다. 잠시 후 다시 시도해주세요."; }
1451 finally { IsGeocoding = false; }
1452 }

다음을 참조함 : _geocodeHttp, Config, GeocodeStatus, IsGeocoding.

◆ GetAdminUsers()

List< ThankYouAdminUser > WeddingThankYou.ViewModels.AdminViewModel.GetAdminUsers ( TenantConfig config)
inlinestaticprivate

Admin Users 값을 가져옵니다.

매개변수
configconfig에 사용할 TenantConfig 값입니다.
반환값
Get Admin Users 작업에서 생성한 List<ThankYouAdminUser> 결과입니다.

AdminViewModel.cs 파일의 1960 번째 라인에서 정의되었습니다.

1960=> config.AdminUsers ??= [];

다음에 의해서 참조됨 : BuildEffectiveAdminUsers(), EnsureAdminUser(), IsAdminUser(), RemoveAdminAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ GetHeroUrl()

string WeddingThankYou.ViewModels.AdminViewModel.GetHeroUrl ( string slug,
string fileName )
inline

Hero Url 값을 가져옵니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
반환값
Get Hero Url 작업에서 생성한 string 결과입니다.

AdminViewModel.cs 파일의 1592 번째 라인에서 정의되었습니다.

1592=> _photos.GetHeroUrl(slug, fileName);

다음을 참조함 : _photos.

◆ GetMusicUrl()

string WeddingThankYou.ViewModels.AdminViewModel.GetMusicUrl ( string slug,
string fileName )
inline

Music Url 값을 가져옵니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
반환값
Get Music Url 작업에서 생성한 string 결과입니다.

AdminViewModel.cs 파일의 1658 번째 라인에서 정의되었습니다.

1658=> _photos.GetMusicUrl(slug, fileName);

다음을 참조함 : _photos.

◆ GetOgImageUrl()

string WeddingThankYou.ViewModels.AdminViewModel.GetOgImageUrl ( string slug,
string fileName )
inline

Og Image Url 값을 가져옵니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
반환값
Get Og Image Url 작업에서 생성한 string 결과입니다.

AdminViewModel.cs 파일의 1691 번째 라인에서 정의되었습니다.

1691=> _photos.GetHeroUrl(slug, fileName);

다음을 참조함 : _photos.

◆ GetPhotoUrl()

string WeddingThankYou.ViewModels.AdminViewModel.GetPhotoUrl ( string slug,
string fileName )
inline

Photo Url 값을 가져옵니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
반환값
Get Photo Url 작업에서 생성한 string 결과입니다.

AdminViewModel.cs 파일의 1559 번째 라인에서 정의되었습니다.

1559=> _photos.GetPhotoUrl(slug, fileName);

다음을 참조함 : _photos.

◆ GetRoadMapUrl()

string WeddingThankYou.ViewModels.AdminViewModel.GetRoadMapUrl ( string slug,
string fileName )
inline

Road Map Url 값을 가져옵니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
반환값
Get Road Map Url 작업에서 생성한 string 결과입니다.

AdminViewModel.cs 파일의 1625 번째 라인에서 정의되었습니다.

1625=> _photos.GetRoadMapUrl(slug, fileName);

다음을 참조함 : _photos.

◆ GetThumbUrl()

string WeddingThankYou.ViewModels.AdminViewModel.GetThumbUrl ( string slug,
string fileName )
inline

Thumb Url 값을 가져옵니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
반환값
Get Thumb Url 작업에서 생성한 string 결과입니다.

AdminViewModel.cs 파일의 1526 번째 라인에서 정의되었습니다.

1526=> _photos.GetThumbUrl(slug, fileName);

다음을 참조함 : _photos.

◆ GetVideoUrl()

string WeddingThankYou.ViewModels.AdminViewModel.GetVideoUrl ( string slug,
string fileName )
inline

Video Url 값을 가져옵니다.

매개변수
slugslug에 사용할 string 값입니다.
fileNamefile Name에 사용할 string 값입니다.
반환값
Get Video Url 작업에서 생성한 string 결과입니다.

AdminViewModel.cs 파일의 1724 번째 라인에서 정의되었습니다.

1724=> _photos.GetVideoUrl(slug, fileName);

다음을 참조함 : _photos.

◆ InitializeAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.InitializeAsync ( string slug,
CancellationToken ct = default )
inline

Initialize Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Initialize Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 371 번째 라인에서 정의되었습니다.

372 {
373 StatusMessage = "";
374 await RefreshCurrentUserAsync().ConfigureAwait(false);
375
376 var config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
377 if (config is null)
378 {
379 return;
380 }
381
382 var user = await _userContext.GetCurrentAsync().ConfigureAwait(false);
383 IsOwner = IsOwnerUser(config, user);
384 IsLinkedToCurrentUser = IsAdminUser(config, user);
385 EffectiveAdminUsers = BuildEffectiveAdminUsers(config);
386
387 if (IsLinkedToCurrentUser)
388 {
389 IsAuthenticated = true;
390 await LoadAsync(slug, ct).ConfigureAwait(false);
391 }
392 }

다음을 참조함 : _tenants, _userContext, BuildEffectiveAdminUsers(), EffectiveAdminUsers, IsAdminUser(), IsAuthenticated, IsLinkedToCurrentUser, IsOwner, IsOwnerUser(), LoadAsync(), RefreshCurrentUserAsync(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ IsAdminUser()

bool WeddingThankYou.ViewModels.AdminViewModel.IsAdminUser ( TenantConfig config,
ThankYouCurrentUser user )
inlinestaticprivate

Is Admin User 조건을 확인합니다.

매개변수
configconfig에 사용할 TenantConfig 값입니다.
useruser에 사용할 ThankYouCurrentUser 값입니다.
반환값
Is Admin User 조건이 충족되면 true이고, 그렇지 않으면 false입니다.

AdminViewModel.cs 파일의 2031 번째 라인에서 정의되었습니다.

2032 {
2033 if (!user.IsAuthenticated) return false;
2034 if (IsOwnerUser(config, user)) return true;
2035 return GetAdminUsers(config).Any(x => string.Equals(x.UserId, user.Id, StringComparison.Ordinal));
2036 }

다음을 참조함 : GetAdminUsers(), IsOwnerUser(), WeddingThankYou.Services.ThankYouCurrentUser().

다음에 의해서 참조됨 : InitializeAsync(), LoginAsync().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IsOwnerUser()

bool WeddingThankYou.ViewModels.AdminViewModel.IsOwnerUser ( TenantConfig config,
ThankYouCurrentUser user )
inlinestaticprivate

Is Owner User 조건을 확인합니다.

매개변수
configconfig에 사용할 TenantConfig 값입니다.
useruser에 사용할 ThankYouCurrentUser 값입니다.
반환값
Is Owner User 조건이 충족되면 true이고, 그렇지 않으면 false입니다.

AdminViewModel.cs 파일의 1994 번째 라인에서 정의되었습니다.

1994 =>
1995 user.IsAuthenticated &&
1996 !string.IsNullOrWhiteSpace(config.OwnerUserId) &&
1997 string.Equals(config.OwnerUserId, user.Id, StringComparison.Ordinal);

다음을 참조함 : WeddingThankYou.Services.ThankYouCurrentUser().

다음에 의해서 참조됨 : InitializeAsync(), IsAdminUser(), LoginAsync(), RemoveAdminAsync().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ LoadAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.LoadAsync ( string slug,
CancellationToken ct = default )
inline

Async 데이터를 불러옵니다.

매개변수
slugslug에 사용할 string 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Load Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 588 번째 라인에서 정의되었습니다.

589 {
590 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false)
591 ?? new TenantConfig { Slug = slug };
592 ThankYouDesignCatalog.Normalize(Config);
593 Gallery = await _photos.GetGalleryAsync(slug, ct).ConfigureAwait(false);
594 EffectiveAdminUsers = BuildEffectiveAdminUsers(Config);
595
596 EffectiveMediaPolicy = await _mediaPolicyResolver.ResolveAsync(Config, ct).ConfigureAwait(false);
597
598 var effectiveMb = EffectiveMediaPolicy.VideoMaxFileSizeMb;
599 MaxVideoSizeLabel = effectiveMb <= 0 ? "무제한" : $"최대 {effectiveMb}MB";
600
601 MaxVideoCount = EffectiveMediaPolicy.VideoMaxCount;
602
603 IsLoaded = true;
604 }

다음을 참조함 : _mediaPolicyResolver, _photos, _tenants, BuildEffectiveAdminUsers(), Config, EffectiveAdminUsers, EffectiveMediaPolicy, Gallery, IsLoaded, MaxVideoCount, MaxVideoSizeLabel, WeddingThankYou.Models.ThankYouDesignCatalog.Normalize().

다음에 의해서 참조됨 : InitializeAsync(), LoginAsSuperAdminAsync().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ LoginAsSuperAdminAsync()

async Task< bool > WeddingThankYou.ViewModels.AdminViewModel.LoginAsSuperAdminAsync ( string slug,
string? sessionToken,
CancellationToken ct = default )
inline

Login As Super Admin Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
sessionTokensession Token에 사용할 string? 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Login As Super Admin Async 작업에서 생성한 Task<bool> 결과입니다.

AdminViewModel.cs 파일의 533 번째 라인에서 정의되었습니다.

534 {
535 if (!_superAdminTokens.ValidateToken(sessionToken))
536 {
537 return false;
538 }
539
540 var config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
541 if (config is null)
542 {
543 StatusMessage = "존재하지 않는 슬러그입니다.";
544 return false;
545 }
546
547 IsAuthenticated = true;
548 IsLinkedToCurrentUser = false;
549 IsOwner = false;
550 EffectiveAdminUsers = BuildEffectiveAdminUsers(config);
551 StatusMessage = "슈퍼관리자 권한으로 접속했습니다.";
552 await LoadAsync(slug, ct).ConfigureAwait(false);
553 return true;
554 }

다음을 참조함 : _superAdminTokens, _tenants, BuildEffectiveAdminUsers(), EffectiveAdminUsers, IsAuthenticated, IsLinkedToCurrentUser, IsOwner, LoadAsync(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ LoginAsync()

async Task< bool > WeddingThankYou.ViewModels.AdminViewModel.LoginAsync ( string slug,
CancellationToken ct = default )
inline

Login Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Login Async 작업에서 생성한 Task<bool> 결과입니다.

AdminViewModel.cs 파일의 426 번째 라인에서 정의되었습니다.

427 {
428 var config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
429 if (config is null) { StatusMessage = "존재하지 않는 슬러그입니다."; return false; }
430
431 var user = await _userContext.GetCurrentAsync().ConfigureAwait(false);
432 await RefreshCurrentUserAsync().ConfigureAwait(false);
433
434 if (IsAdminUser(config, user))
435 {
436 IsAuthenticated = true;
437 IsLinkedToCurrentUser = true;
438 IsOwner = IsOwnerUser(config, user);
439 EffectiveAdminUsers = BuildEffectiveAdminUsers(config);
440 StatusMessage = "";
441 return true;
442 }
443
444 var verification = DreaminePasswordHasher.VerifyPassword(LoginPassword, config.PasswordHash, out var upgradedHash);
445 IsAuthenticated = verification is not PasswordHashVerificationResult.Failed;
446 if (!IsAuthenticated)
447 {
448 StatusMessage = "비밀번호가 틀렸습니다.";
449 return false;
450 }
451
452 if (verification is PasswordHashVerificationResult.SuccessRehashNeeded && upgradedHash is not null)
453 {
454 config.PasswordHash = upgradedHash;
455 await _tenants.SaveAsync(config, ct).ConfigureAwait(false);
456 }
457
458 if (user.IsAuthenticated && string.IsNullOrWhiteSpace(config.OwnerUserId))
459 {
460 config.OwnerUserId = user.Id;
461 config.OwnerProvider = user.Provider;
462 config.OwnerEmail = user.Email;
463 config.OwnerDisplayName = user.DisplayName;
464 config.OwnerLinkedAt = DateTime.Now;
465 EnsureAdminUser(config, user, "Owner");
466 await _tenants.SaveAsync(config, ct).ConfigureAwait(false);
467 IsLinkedToCurrentUser = true;
468 IsOwner = true;
469 EffectiveAdminUsers = BuildEffectiveAdminUsers(config);
470 StatusMessage = "CodeMaru/Dreamine 계정에 대표 관리자로 연결되었습니다. 다음부터는 공용 로그인으로 관리할 수 있습니다.";
471 }
472 else if (user.IsAuthenticated)
473 {
474 EnsureAdminUser(config, user, "Admin");
475 await _tenants.SaveAsync(config, ct).ConfigureAwait(false);
476 IsLinkedToCurrentUser = true;
477 IsOwner = IsOwnerUser(config, user);
478 EffectiveAdminUsers = BuildEffectiveAdminUsers(config);
479 StatusMessage = "현재 CodeMaru/Dreamine 계정이 이 감사장의 관리자로 추가되었습니다.";
480 }
481 else if (!user.IsAuthenticated && string.IsNullOrWhiteSpace(config.OwnerUserId))
482 {
483 StatusMessage = "로그인은 성공했습니다. 공용 계정에 연결하려면 먼저 CodeMaru/Dreamine 로그인을 해주세요.";
484 }
485 else
486 {
487 StatusMessage = "";
488 }
489
490 return IsAuthenticated;
491 }

다음을 참조함 : _tenants, _userContext, BuildEffectiveAdminUsers(), EffectiveAdminUsers, EnsureAdminUser(), IsAdminUser(), IsAuthenticated, IsLinkedToCurrentUser, IsOwner, IsOwnerUser(), LoginPassword, RefreshCurrentUserAsync(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MoveGalleryPhotoAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.MoveGalleryPhotoAsync ( string fileName,
int offset,
CancellationToken ct = default )
inline

Move Gallery Photo Async 작업을 수행합니다.

매개변수
fileNamefile Name에 사용할 string 값입니다.
offsetoffset에 사용할 int 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Move Gallery Photo Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1246 번째 라인에서 정의되었습니다.

1247 {
1248 if (Config is null) return;
1249 try
1250 {
1251 NormalizeGalleryFileOrder();
1252 var index = Config.GalleryFileNames.FindIndex(x => string.Equals(x, fileName, StringComparison.OrdinalIgnoreCase));
1253 if (index < 0) return;
1254
1255 var target = Math.Clamp(index + offset, 0, Config.GalleryFileNames.Count - 1);
1256 if (index == target) return;
1257
1258 Config.GalleryFileNames.RemoveAt(index);
1259 Config.GalleryFileNames.Insert(target, fileName);
1260 await _tenants.SaveAsync(Config, ct).ConfigureAwait(false);
1261 Gallery = await _photos.GetGalleryAsync(Config.Slug, ct).ConfigureAwait(false);
1262 StatusMessage = "사진 노출 순서가 저장되었습니다.";
1263 }
1264 catch (Exception ex) { StatusMessage = $"순서 변경 오류: {ex.Message}"; }
1265 }

다음을 참조함 : _photos, _tenants, Config, Gallery, NormalizeGalleryFileOrder(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MoveGalleryPhotoToAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.MoveGalleryPhotoToAsync ( string fileName,
bool first,
CancellationToken ct = default )
inline

Move Gallery Photo To Async 작업을 수행합니다.

매개변수
fileNamefile Name에 사용할 string 값입니다.
firstfirst에 사용할 bool 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Move Gallery Photo To Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1307 번째 라인에서 정의되었습니다.

1308 {
1309 if (Config is null) return;
1310 try
1311 {
1312 NormalizeGalleryFileOrder();
1313 var index = Config.GalleryFileNames.FindIndex(x => string.Equals(x, fileName, StringComparison.OrdinalIgnoreCase));
1314 if (index < 0) return;
1315
1316 Config.GalleryFileNames.RemoveAt(index);
1317 Config.GalleryFileNames.Insert(first ? 0 : Config.GalleryFileNames.Count, fileName);
1318 await _tenants.SaveAsync(Config, ct).ConfigureAwait(false);
1319 Gallery = await _photos.GetGalleryAsync(Config.Slug, ct).ConfigureAwait(false);
1320 StatusMessage = "사진 노출 순서가 저장되었습니다.";
1321 }
1322 catch (Exception ex) { StatusMessage = $"순서 변경 오류: {ex.Message}"; }
1323 }

다음을 참조함 : _photos, _tenants, Config, Gallery, NormalizeGalleryFileOrder(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ NormalizeGalleryFileOrder()

void WeddingThankYou.ViewModels.AdminViewModel.NormalizeGalleryFileOrder ( )
inlineprivate

Normalize Gallery File Order 작업을 수행합니다.

AdminViewModel.cs 파일의 1333 번째 라인에서 정의되었습니다.

1334 {
1335 if (Config is null) return;
1336 var existing = Gallery.Select(x => x.FileName).ToHashSet(StringComparer.OrdinalIgnoreCase);
1337 Config.GalleryFileNames = Config.GalleryFileNames
1338 .Where(existing.Contains)
1339 .Distinct(StringComparer.OrdinalIgnoreCase)
1340 .ToList();
1341
1342 foreach (var photo in Gallery)
1343 {
1344 if (!Config.GalleryFileNames.Contains(photo.FileName, StringComparer.OrdinalIgnoreCase))
1345 {
1346 Config.GalleryFileNames.Add(photo.FileName);
1347 }
1348 }
1349 }

다음을 참조함 : Config, Gallery.

다음에 의해서 참조됨 : MoveGalleryPhotoAsync(), MoveGalleryPhotoToAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RefreshCurrentUserAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.RefreshCurrentUserAsync ( )
inlineprivate

Refresh Current User Async 작업을 수행합니다.

반환값
Refresh Current User Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 622 번째 라인에서 정의되었습니다.

623 {
624 var user = await _userContext.GetCurrentAsync().ConfigureAwait(false);
625 IsSignedIn = user.IsAuthenticated;
626 CurrentUserLabel = user.IsAuthenticated
627 ? string.IsNullOrWhiteSpace(user.DisplayName)
628 ? user.Provider
629 : $"{user.DisplayName} ({user.Provider})"
630 : "";
631 }

다음을 참조함 : _userContext, CurrentUserLabel, IsSignedIn.

다음에 의해서 참조됨 : InitializeAsync(), LoginAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ RemoveAdminAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.RemoveAdminAsync ( string userId,
CancellationToken ct = default )
inline

Admin Async 항목을 제거합니다.

매개변수
userIduser Id에 사용할 string 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Remove Admin Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1017 번째 라인에서 정의되었습니다.

1018 {
1019 if (Config is null) return;
1020 var user = await _userContext.GetCurrentAsync().ConfigureAwait(false);
1021 if (!IsOwnerUser(Config, user))
1022 {
1023 StatusMessage = "대표 관리자만 관리자 계정을 삭제할 수 있습니다.";
1024 return;
1025 }
1026
1027 if (string.Equals(Config.OwnerUserId, userId, StringComparison.Ordinal))
1028 {
1029 StatusMessage = "대표 관리자는 삭제할 수 없습니다.";
1030 return;
1031 }
1032
1033 var removed = GetAdminUsers(Config).RemoveAll(x => string.Equals(x.UserId, userId, StringComparison.Ordinal));
1034 if (removed == 0)
1035 {
1036 StatusMessage = "삭제할 관리자를 찾을 수 없습니다.";
1037 return;
1038 }
1039
1040 await _tenants.SaveAsync(Config, ct).ConfigureAwait(false);
1041 EffectiveAdminUsers = BuildEffectiveAdminUsers(Config);
1042 StatusMessage = "관리자 계정이 삭제되었습니다.";
1043 }

다음을 참조함 : _tenants, _userContext, BuildEffectiveAdminUsers(), Config, EffectiveAdminUsers, GetAdminUsers(), IsOwnerUser(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ SaveConfigAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.SaveConfigAsync ( CancellationToken ct = default)
inline

Config Async 데이터를 저장합니다.

매개변수
ct취소 요청을 감시하는 토큰입니다.
반환값
Save Config Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 657 번째 라인에서 정의되었습니다.

658 {
659 if (Config is null) return;
660 try
661 {
662 if (!ValidateLayoutForSave(Config))
663 {
664 return;
665 }
666
667 if (!ValidateThemeForSave(Config))
668 {
669 return;
670 }
671
672 ThankYouDesignCatalog.Normalize(Config);
673 Config.PasswordHash = DreaminePasswordHasher.HashPlainTextForStorage(Config.PasswordHash);
674 await _tenants.SaveAsync(Config, ct).ConfigureAwait(false);
675 EffectiveAdminUsers = BuildEffectiveAdminUsers(Config);
676 StatusMessage = "설정이 저장되었습니다.";
677 }
678 catch (Exception ex) { StatusMessage = $"저장 오류: {ex.Message}"; }
679 }

다음을 참조함 : _tenants, BuildEffectiveAdminUsers(), Config, EffectiveAdminUsers, WeddingThankYou.Models.ThankYouDesignCatalog.Normalize(), StatusMessage, ValidateLayoutForSave(), ValidateThemeForSave().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ SaveStoryChapterAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.SaveStoryChapterAsync ( StoryChapter chapter,
CancellationToken ct = default )
inline

Story Chapter Async 데이터를 저장합니다.

매개변수
chapterchapter에 사용할 StoryChapter 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Save Story Chapter Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 713 번째 라인에서 정의되었습니다.

714 {
715 if (Config is null) return;
716 try
717 {
718 ThankYouDesignCatalog.Normalize(Config);
719 var chapters = Config.StoryChapters;
720 var index = chapters.FindIndex(x => x.ChapterNumber == chapter.ChapterNumber);
721 var normalized = WeddingStoryChapterDefaults.Clone(chapter);
722 normalized.Label = string.IsNullOrWhiteSpace(normalized.Label)
723 ? $"CHAPTER {Math.Max(1, normalized.ChapterNumber):00}"
724 : normalized.Label.Trim();
725 normalized.Title = string.IsNullOrWhiteSpace(normalized.Title)
726 ? "스토리"
727 : normalized.Title.Trim();
728
729 if (index >= 0)
730 {
731 chapters[index] = normalized;
732 }
733 else
734 {
735 chapters.Add(normalized);
736 Config.StoryChapters = WeddingStoryChapterDefaults.Normalize(chapters);
737 }
738
739 await _tenants.SaveAsync(Config, ct).ConfigureAwait(false);
740 StatusMessage = $"{normalized.Label} 챕터가 저장되었습니다.";
741 }
742 catch (Exception ex)
743 {
744 StatusMessage = $"챕터 저장 오류: {ex.Message}";
745 }
746 }

다음을 참조함 : _tenants, Config, WeddingThankYou.Models.ThankYouDesignCatalog.Normalize(), StatusMessage.

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ SetStatusMessage()

void WeddingThankYou.ViewModels.AdminViewModel.SetStatusMessage ( string message)
inline

Status Message 값을 설정합니다.

매개변수
message처리할 메시지입니다.

AdminViewModel.cs 파일의 334 번째 라인에서 정의되었습니다.

335 {
336 StatusMessage = message;
337 }

다음을 참조함 : StatusMessage.

◆ UploadGalleryAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.UploadGalleryAsync ( string slug,
IBrowserFile file,
CancellationToken ct = default )
inline

Upload Gallery Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
filefile에 사용할 IBrowserFile 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Upload Gallery Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1085 번째 라인에서 정의되었습니다.

1086 {
1087 IsUploading = true;
1088 StatusMessage = "";
1089 try
1090 {
1091 await _photos.UploadAsync(slug, file, ct).ConfigureAwait(false);
1092 // Config도 갱신해야 이후 설정 저장 시 GalleryFileNames가 날아가지 않음
1093 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1094 Gallery = await _photos.GetGalleryAsync(slug, ct).ConfigureAwait(false);
1095 StatusMessage = $"{file.Name} 업로드 완료";
1096 }
1097 catch (Exception ex) { StatusMessage = $"업로드 오류: {ex.Message}"; }
1098 finally { IsUploading = false; }
1099 }

다음을 참조함 : _photos, _tenants, Config, Gallery, IsUploading, StatusMessage.

◆ UploadHeroAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.UploadHeroAsync ( string slug,
IBrowserFile file,
CancellationToken ct = default )
inline

Upload Hero Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
filefile에 사용할 IBrowserFile 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Upload Hero Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1141 번째 라인에서 정의되었습니다.

1142 {
1143 IsUploading = true;
1144 try
1145 {
1146 await _photos.UploadHeroAsync(slug, file, ct).ConfigureAwait(false);
1147 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1148 StatusMessage = "히어로 이미지 업로드 완료";
1149 }
1150 catch (Exception ex) { StatusMessage = $"히어로 업로드 오류: {ex.Message}"; }
1151 finally { IsUploading = false; }
1152 }

다음을 참조함 : _photos, _tenants, Config, IsUploading, StatusMessage.

◆ UploadMusicAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.UploadMusicAsync ( string slug,
IBrowserFile file,
CancellationToken ct = default )
inline

Upload Music Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
filefile에 사용할 IBrowserFile 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Upload Music Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1923 번째 라인에서 정의되었습니다.

1924 {
1925 IsUploading = true;
1926 try
1927 {
1928 await _photos.UploadMusicAsync(slug, file, ct).ConfigureAwait(false);
1929 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1930 StatusMessage = "배경 음악 업로드 완료";
1931 }
1932 catch (Exception ex) { StatusMessage = $"음악 업로드 오류: {ex.Message}"; }
1933 finally { IsUploading = false; }
1934 }

다음을 참조함 : _photos, _tenants, Config, IsUploading, StatusMessage.

◆ UploadOgImageAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.UploadOgImageAsync ( string slug,
IBrowserFile file,
CancellationToken ct = default )
inline

Upload Og Image Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
filefile에 사용할 IBrowserFile 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Upload Og Image Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1766 번째 라인에서 정의되었습니다.

1767 {
1768 IsUploading = true;
1769 try
1770 {
1771 await _photos.UploadOgImageAsync(slug, file, ct).ConfigureAwait(false);
1772 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1773 StatusMessage = "미리보기 이미지 업로드 완료";
1774 }
1775 catch (Exception ex) { StatusMessage = $"미리보기 이미지 오류: {ex.Message}"; }
1776 finally { IsUploading = false; }
1777 }

다음을 참조함 : _photos, _tenants, Config, IsUploading, StatusMessage.

◆ UploadRoadMapAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.UploadRoadMapAsync ( string slug,
IBrowserFile file,
CancellationToken ct = default )
inline

Upload Road Map Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
filefile에 사용할 IBrowserFile 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Upload Road Map Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1391 번째 라인에서 정의되었습니다.

1392 {
1393 IsUploading = true;
1394 try
1395 {
1396 await _photos.UploadRoadMapAsync(slug, file, ct).ConfigureAwait(false);
1397 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1398 StatusMessage = "약도 이미지 업로드 완료";
1399 }
1400 catch (Exception ex) { StatusMessage = $"약도 업로드 오류: {ex.Message}"; }
1401 finally { IsUploading = false; }
1402 }

다음을 참조함 : _photos, _tenants, Config, IsUploading, StatusMessage.

◆ UploadVideoAsync()

async Task WeddingThankYou.ViewModels.AdminViewModel.UploadVideoAsync ( string slug,
IBrowserFile file,
CancellationToken ct = default )
inline

Upload Video Async 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
filefile에 사용할 IBrowserFile 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Upload Video Async 작업에서 생성한 Task 결과입니다.

AdminViewModel.cs 파일의 1819 번째 라인에서 정의되었습니다.

1820 {
1821 IsUploading = true;
1822 try
1823 {
1824 await _photos.UploadVideoAsync(slug, file, ct).ConfigureAwait(false);
1825 Config = await _tenants.GetAsync(slug, ct).ConfigureAwait(false);
1826 StatusMessage = "동영상 업로드 완료";
1827 }
1828 catch (Exception ex) { StatusMessage = $"동영상 업로드 오류: {ex.Message}"; }
1829 finally { IsUploading = false; }
1830 }

다음을 참조함 : _photos, _tenants, Config, IsUploading, StatusMessage.

◆ ValidateLayoutForSave()

bool WeddingThankYou.ViewModels.AdminViewModel.ValidateLayoutForSave ( TenantConfig config)
inlineprivate

Layout For Save 값의 유효성을 검사합니다.

매개변수
configconfig에 사용할 TenantConfig 값입니다.
반환값
Validate Layout For Save 조건이 충족되면 true이고, 그렇지 않으면 false입니다.

AdminViewModel.cs 파일의 880 번째 라인에서 정의되었습니다.

881 {
882 if (!WeddingLayoutCatalog.IsKnownKey(config.ThankYouStyle))
883 {
884 StatusMessage = "저장 오류: 존재하지 않는 레이아웃입니다.";
885 return false;
886 }
887
888 var mode = ThankYouDesignCatalog.ResolveLayoutMode(config.ThankYouStyle);
889 var option = WeddingLayoutCatalog.Instance.Find(mode);
890 if (option is null)
891 {
892 StatusMessage = "저장 오류: 존재하지 않는 레이아웃입니다.";
893 return false;
894 }
895
896 if (!option.IsImplemented)
897 {
898 StatusMessage = "저장 오류: 아직 준비 중인 레이아웃입니다.";
899 return false;
900 }
901
902 var access = new WeddingLayoutAccessState
903 {
904 HasPremiumPlan = config.HasPremiumPlan,
905 UnlockedLayouts = config.UnlockedLayoutModes
906 .Select(WeddingLayoutCatalog.FromLegacyKey)
907 .Where(x => x != WeddingLayoutMode.Unknown)
908 .ToArray(),
909 };
910
911 if (!new WeddingLayoutAccessPolicy().CanUse(option, access))
912 {
913 StatusMessage = "저장 오류: 프리미엄 레이아웃은 플랜 또는 잠금 해제 후 저장할 수 있습니다.";
914 return false;
915 }
916
917 return true;
918 }

다음을 참조함 : WeddingThankYou.Models.TenantConfig.HasPremiumPlan, WeddingThankYou.Models.ThankYouDesignCatalog.ResolveLayoutMode(), StatusMessage, WeddingThankYou.Models.TenantConfig.ThankYouStyle.

다음에 의해서 참조됨 : SaveConfigAsync().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:
이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ ValidateThemeForSave()

bool WeddingThankYou.ViewModels.AdminViewModel.ValidateThemeForSave ( TenantConfig config)
inlineprivate

Theme For Save 값의 유효성을 검사합니다.

매개변수
configconfig에 사용할 TenantConfig 값입니다.
반환값
Validate Theme For Save 조건이 충족되면 true이고, 그렇지 않으면 false입니다.

AdminViewModel.cs 파일의 944 번째 라인에서 정의되었습니다.

945 {
946 config.UnlockedThemeKeys ??= new();
947 if (!WeddingThemeCatalog.IsKnownKey(config.ThemeName))
948 {
949 StatusMessage = "저장 오류: 존재하지 않는 테마입니다.";
950 return false;
951 }
952
953 var option = WeddingThemeCatalog.Instance.Find(config.ThemeName);
954 if (option is null)
955 {
956 StatusMessage = "저장 오류: 존재하지 않는 테마입니다.";
957 return false;
958 }
959
960 if (!option.IsImplemented)
961 {
962 StatusMessage = "저장 오류: 아직 준비 중인 테마입니다.";
963 return false;
964 }
965
966 var access = new WeddingThemeAccessState
967 {
968 HasPremiumPlan = config.HasPremiumPlan,
969 UnlockedThemeKeys = config.UnlockedThemeKeys
970 .Select(WeddingThemeCatalog.NormalizeKey)
971 .Where(WeddingThemeCatalog.IsKnownKey)
972 .ToArray(),
973 };
974
975 if (!new WeddingThemeAccessPolicy().CanUse(option, access))
976 {
977 StatusMessage = "저장 오류: 프리미엄 테마는 플랜 또는 잠금 해제 후 저장할 수 있습니다.";
978 return false;
979 }
980
981 config.ThemeName = option.Key;
982 return true;
983 }

다음을 참조함 : WeddingThankYou.Models.TenantConfig.HasPremiumPlan, StatusMessage, WeddingThankYou.Models.TenantConfig.ThemeName.

다음에 의해서 참조됨 : SaveConfigAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

멤버 데이터 문서화

◆ _geocodeHttp

readonly HttpClient WeddingThankYou.ViewModels.AdminViewModel._geocodeHttp
staticprivate
초기값:
= new()
{
DefaultRequestHeaders = { { "User-Agent", "WeddingThankYou/1.0 (contact: admin@codemaru.co.kr)" } }
}

geocode Http 값을 보관합니다.

AdminViewModel.cs 파일의 85 번째 라인에서 정의되었습니다.

86 {
87 DefaultRequestHeaders = { { "User-Agent", "WeddingThankYou/1.0 (contact: admin@codemaru.co.kr)" } }
88 };

다음에 의해서 참조됨 : GeocodeAsync().

◆ _mediaPolicyResolver

readonly IMediaQuotaPolicyResolver WeddingThankYou.ViewModels.AdminViewModel._mediaPolicyResolver
private

media Policy Resolver 값을 보관합니다.

AdminViewModel.cs 파일의 66 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : AdminViewModel(), LoadAsync().

◆ _opts

readonly WeddingOptions WeddingThankYou.ViewModels.AdminViewModel._opts
private

opts 값을 보관합니다.

AdminViewModel.cs 파일의 48 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : AdminViewModel(), GenerateMapLinks().

◆ _photos

◆ _superAdminTokens

readonly ISuperAdminSessionTokenService WeddingThankYou.ViewModels.AdminViewModel._superAdminTokens
private

super Admin Tokens 값을 보관합니다.

AdminViewModel.cs 파일의 75 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : AdminViewModel(), LoginAsSuperAdminAsync().

◆ _tenants

◆ _userContext

readonly ThankYouUserContext WeddingThankYou.ViewModels.AdminViewModel._userContext
private

user Context 값을 보관합니다.

AdminViewModel.cs 파일의 57 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : AdminViewModel(), InitializeAsync(), LoginAsync(), RefreshCurrentUserAsync(), RemoveAdminAsync().

속성 문서화

◆ Config

◆ CurrentUserLabel

string WeddingThankYou.ViewModels.AdminViewModel.CurrentUserLabel = ""
getprivate set

Current User Label 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 279 번째 라인에서 정의되었습니다.

279{ get; private set; } = "";

다음에 의해서 참조됨 : RefreshCurrentUserAsync().

◆ EffectiveAdminUsers

IReadOnlyList<ThankYouAdminUser> WeddingThankYou.ViewModels.AdminViewModel.EffectiveAdminUsers = []
getprivate set

Effective Admin Users 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 261 번째 라인에서 정의되었습니다.

261{ get; private set; } = [];

다음에 의해서 참조됨 : InitializeAsync(), LoadAsync(), LoginAsSuperAdminAsync(), LoginAsync(), RemoveAdminAsync(), SaveConfigAsync().

◆ EffectiveMediaPolicy

EffectiveMediaPolicy? WeddingThankYou.ViewModels.AdminViewModel.EffectiveMediaPolicy
getprivate set

현재 계정에 적용되는 최종 미디어 정책입니다.

AdminViewModel.cs 파일의 188 번째 라인에서 정의되었습니다.

188{ get; private set; }

다음에 의해서 참조됨 : LoadAsync().

◆ Gallery

IReadOnlyList<PhotoInfo> WeddingThankYou.ViewModels.AdminViewModel.Gallery = []
getprivate set

Gallery 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 207 번째 라인에서 정의되었습니다.

207{ get; private set; } = [];

다음에 의해서 참조됨 : DeletePhotoAsync(), LoadAsync(), MoveGalleryPhotoAsync(), MoveGalleryPhotoToAsync(), NormalizeGalleryFileOrder(), UploadGalleryAsync().

◆ GeocodeStatus

string WeddingThankYou.ViewModels.AdminViewModel.GeocodeStatus = ""
getprivate set

Geocode Status 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 306 번째 라인에서 정의되었습니다.

306{ get; private set; } = "";

다음에 의해서 참조됨 : GeocodeAsync().

◆ IsAuthenticated

bool WeddingThankYou.ViewModels.AdminViewModel.IsAuthenticated
getprivate set

Is Authenticated 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 225 번째 라인에서 정의되었습니다.

225{ get; private set; }

다음에 의해서 참조됨 : InitializeAsync(), LoginAsSuperAdminAsync(), LoginAsync().

◆ IsGeocoding

bool WeddingThankYou.ViewModels.AdminViewModel.IsGeocoding
getprivate set

Is Geocoding 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 297 번째 라인에서 정의되었습니다.

297{ get; private set; }

다음에 의해서 참조됨 : GeocodeAsync().

◆ IsLinkedToCurrentUser

bool WeddingThankYou.ViewModels.AdminViewModel.IsLinkedToCurrentUser
getprivate set

Is Linked To Current User 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 243 번째 라인에서 정의되었습니다.

243{ get; private set; }

다음에 의해서 참조됨 : InitializeAsync(), LoginAsSuperAdminAsync(), LoginAsync().

◆ IsLoaded

bool WeddingThankYou.ViewModels.AdminViewModel.IsLoaded
getprivate set

Is Loaded 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 216 번째 라인에서 정의되었습니다.

216{ get; private set; }

다음에 의해서 참조됨 : LoadAsync().

◆ IsOwner

bool WeddingThankYou.ViewModels.AdminViewModel.IsOwner
getprivate set

Is Owner 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 252 번째 라인에서 정의되었습니다.

252{ get; private set; }

다음에 의해서 참조됨 : InitializeAsync(), LoginAsSuperAdminAsync(), LoginAsync().

◆ IsSignedIn

bool WeddingThankYou.ViewModels.AdminViewModel.IsSignedIn
getprivate set

Is Signed In 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 234 번째 라인에서 정의되었습니다.

234{ get; private set; }

다음에 의해서 참조됨 : RefreshCurrentUserAsync().

◆ IsUploading

bool WeddingThankYou.ViewModels.AdminViewModel.IsUploading
getprivate set

Is Uploading 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 288 번째 라인에서 정의되었습니다.

288{ get; private set; }

다음에 의해서 참조됨 : UploadGalleryAsync(), UploadHeroAsync(), UploadMusicAsync(), UploadOgImageAsync(), UploadRoadMapAsync(), UploadVideoAsync().

◆ LoginPassword

string WeddingThankYou.ViewModels.AdminViewModel.LoginPassword = ""
getset

Login Password 값을 가져오거나 설정합니다.

AdminViewModel.cs 파일의 316 번째 라인에서 정의되었습니다.

316{ get; set; } = "";

다음에 의해서 참조됨 : LoginAsync().

◆ MaxVideoCount

int WeddingThankYou.ViewModels.AdminViewModel.MaxVideoCount = 6
getprivate set

동영상 업로드 최대 개수 (0이면 무제한).

AdminViewModel.cs 파일의 179 번째 라인에서 정의되었습니다.

179{ get; private set; } = 6;

다음에 의해서 참조됨 : LoadAsync().

◆ MaxVideoSizeLabel

string WeddingThankYou.ViewModels.AdminViewModel.MaxVideoSizeLabel = "최대 200MB"
getprivate set

동영상 업로드 최대 용량 안내 문구 (예: "최대 200MB" 또는 "무제한").

AdminViewModel.cs 파일의 170 번째 라인에서 정의되었습니다.

170{ get; private set; } = "최대 200MB";

다음에 의해서 참조됨 : LoadAsync().

◆ StatusMessage

string WeddingThankYou.ViewModels.AdminViewModel.StatusMessage = ""
getprivate set

이 클래스에 대한 문서화 페이지는 다음의 파일로부터 생성되었습니다.: